diff --git a/benchmarks/aging/mailserver/config.ini b/benchmarks/aging/mailserver/config.ini new file mode 100644 index 000000000..93a34e846 --- /dev/null +++ b/benchmarks/aging/mailserver/config.ini @@ -0,0 +1,11 @@ +[Parameters] +workingpartition = /dev/sdb1 +workingdir = /mnt/benchmark +fstype = ext4 +checkoutspergrep = 1000 +greprandom = 8TCg8BVMrUz4xoaU +totalcheckouts = 60001 +pretestremount = True +writeamplength = 100 +cleantest = True + diff --git a/benchmarks/aging/mailserver/mailserver-aging.py b/benchmarks/aging/mailserver/mailserver-aging.py new file mode 100755 index 000000000..3515a5174 --- /dev/null +++ b/benchmarks/aging/mailserver/mailserver-aging.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +import imaplib +import sys +import random +import os +import threading +import time +import types +import subprocess + +SERVER = "localhost" +USER = ["ftfstest1", "ftfstest2", "ftfstest3", "ftfstest4", "ftfstest5", "ftfstest6", "ftfstest7", "ftfstest8", "ftfstest9", "ftfstest10", "ftfstest11", "ftfstest12", "ftfstest13", "ftfstest14", "ftfstest15", "ftfstest16"] +PASS = ["oscarlab", "oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab"] + +n_user = 2 +n_box = 80 +boxsize = 1000 +max_msg_len = 32768 +run_time = 1800 +n_top = 8000 + +def worker_thread(i, n_op_thread, running) : + m = imaplib.IMAP4_SSL(SERVER) + m.login(USER[i], PASS[i]) + while not running.isSet() : + pass + n_ops = [0] * 3 +# while running.isSet() : + for i in range(n_top) : + boxnum = random.randint(1, n_box) - 1 + box = "box%d" % boxnum + x = m.select(box) + rand_op = random.randint(1, 2) - 1 + if rand_op == 0 : + msg_len = random.randint(1, max_msg_len) + msg = os.urandom(msg_len) + m.APPEND(box, None, None, msg) + else : + typ, msg_ids = m.search(None, 'ALL') + msgs = msg_ids[0].split() + msg_num = random.randint(1, len(msgs)) - 1 + msg = msgs[msg_num] +# if rand_op == 1 : + m.store(msg, "+FLAGS", "(\\Deleted)") + m.expunge() +# else : +# typ, data = m.fetch(msg, "(RFC822 FLAGS)") +# flagged = 0 +# if type(data[0]) is types.NoneType : +# continue +# flagged = 0 +# for flag in imaplib.ParseFlags(data[0][0]) : +# if (flag == "\Flagged") : +# flagged = 1 +# if flagged : +# m.store(msg, "-FLAGS", "(\\FLAGGED)") +# else : +# m.store(msg, "+FLAGS", "(\\FLAGGED)") + n_ops[rand_op] = n_ops[rand_op] + 1 + subprocess.call('echo "flush" > /proc/toku_flusher', shell=True) + m.logout() + print "Thread %d: append %d delete %d flag change %d" % (i, n_ops[0], n_ops[1], n_ops[2]) + n_op_thread.append(n_ops[0] + n_ops[1] + n_ops[2]) + +print "MAILSERVER AGEING" +f=open('mailservertime.out','a') + +t = [] +running = threading.Event() +n_op_thread = [] +for i in range(n_user) : + tmp_t = threading.Thread(target = worker_thread, args = (i, n_op_thread, running,)) + tmp_t.start() + t.append(tmp_t) + +time.sleep(2) +running.set() +t1 = time.time() +#time.sleep(run_time) +#running.clear() +for i in range(n_user): + t[i].join() +t2 = time.time() +n_op_total = 0 +for i in range(n_user) : + n_op_total = n_op_total + n_op_thread[i] +print "This experiment took %f seconds" % (t2 - t1) +print "%d ops are executed (%f op/s)" % (n_op_total, n_op_total / (t2 - t1)) +f.write("Time\t") +f.write(str(t2 - t1) + '\t') +f.write("Nops\t") +f.write(str(n_op_total) + '\n') + +sys.exit(0) diff --git a/benchmarks/aging/mailserver/mailserver-setup.py b/benchmarks/aging/mailserver/mailserver-setup.py new file mode 100755 index 000000000..3c7a9a852 --- /dev/null +++ b/benchmarks/aging/mailserver/mailserver-setup.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +import imaplib +import sys +import random +import os + +SERVER = "localhost" +USER = ["ftfstest1", "ftfstest2", "ftfstest3", "ftfstest4", "ftfstest5", "ftfstest6", "ftfstest7", "ftfstest8", "ftfstest9", "ftfstest10", "ftfstest11", "ftfstest12", "ftfstest13", "ftfstest14", "ftfstest15", "ftfstest16"] +PASS = ["oscarlab", "oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab","oscarlab"] + +n_user = 2 +n_box = 80 +boxsize = 1000 +max_msg_len = 32768 + +print "MAILSERVER setup" + +for i in range(n_user) : + if 0 == os.fork() : + # Child i + random.seed() + M = imaplib.IMAP4_SSL(SERVER) + M.login(USER[i], PASS[i]) + for j in range(n_box) : + box = "box%d" % j + M.delete(box) + M.create(box) + print "MAILSERVER setup: child %d box %d" % (i, j) + for k in range(boxsize) : + msg_len = random.randint(1, max_msg_len) + msg = os.urandom(msg_len) + M.append(box, None, None, msg) + M.logout() + sys.exit(0) +for i in range(n_user) : + os.wait() +sys.exit(0) diff --git a/benchmarks/aging/mailserver/mailserver-setupdir.sh b/benchmarks/aging/mailserver/mailserver-setupdir.sh new file mode 100755 index 000000000..937dd3a78 --- /dev/null +++ b/benchmarks/aging/mailserver/mailserver-setupdir.sh @@ -0,0 +1,12 @@ +#/bin/bash +#run as root + +for i in $(seq 2) +do + dir=/mnt/benchmark/ftfstest${i}/Maildir + sudo mkdir -p ${dir} + sudo chown -R ftfstest${i}:ftfstest${i} /mnt/benchmark/ftfstest${i} +done + +sudo mkdir -p traces +sudo mkdir -p clean_temp diff --git a/benchmarks/aging/mailserver/resultify.py b/benchmarks/aging/mailserver/resultify.py new file mode 100644 index 000000000..3cde9264e --- /dev/null +++ b/benchmarks/aging/mailserver/resultify.py @@ -0,0 +1,53 @@ +#resultify.py outputs results to csv + +import csv +import json +import subprocess + +with open('results.json') as datafile: + data = json.load(datafile) + +resultfile = open('results.csv','wb') +resultwriter = csv.writer(resultfile,delimiter=',') +resultwriter.writerow( ('FS Size', 'Aged Time', 'Clean Time', 'Aged Total Seek Distance', 'Clean Total Seek Distance') ) + +for i in range(0,len(data)): + print('Processing test ' + str(i)) + #Compute seeks and sectors read form blktrace + subprocess.call('blkparse -q -a issue -f "%S %n \n" -i trace' + str(i).zfill(6) + '.blktrace.0 > agedgrep.txt', cwd='traces', shell=True) + totalseekdistance = 0 + #totalsectors = 0 + with open('traces/agedgrep.txt') as tracefile: + lastsector = -1 + for line in tracefile: + splitline = line.split() + if splitline[0].isdigit(): + sector = int(splitline[0]) + numblocks = int(splitline[1]) + totalseekdistance = totalseekdistance + abs(sector - lastsector) + #if lastsector != sector: + # seeks = seeks + 1 + #totalsectors = totalsectors + numblocks + lastsector = sector + numblocks + + #compute clean reads and sectors read from blktrace + subprocess.call('blkparse -q -a issue -f "%S %n \n" -i cleantrace' + str(i).zfill(6) + '.blktrace.0 > cleangrep.txt', cwd='traces', shell=True) + cleanseekdistance = 0 + #cleantotalsectors = 0 + with open('traces/cleangrep.txt') as tracefile: + lastsector = -1 + for line in tracefile: + splitline = line.split() + if splitline[0].isdigit(): + sector = int(splitline[0]) + numblocks = int(splitline[1]) + cleanseekdistance = cleanseekdistance + abs(sector - lastsector) + #if lastsector != sector: + # cleanseeks = cleanseeks + 1 + #cleantotalsectors = cleantotalsectors + numblocks + lastsector = sector + numblocks + + resultrow = (data[i] + [totalseekdistance, cleanseekdistance]) + resultwriter.writerow(resultrow) + + subprocess.call('sudo rm -f *.txt', cwd='traces', shell=True) diff --git a/benchmarks/aging/mailserver/run-all.py b/benchmarks/aging/mailserver/run-all.py new file mode 100644 index 000000000..5d6d69601 --- /dev/null +++ b/benchmarks/aging/mailserver/run-all.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +#run-all.py +#Improved version of the aging grep test with blktrace, backups, and config files. Running without a config file will generate one with default values. + +import time +import subprocess +from subprocess import CalledProcessError +import ConfigParser +import os.path +import sys + +#Global variables: parameters for the test. Assigned by initialize(). +WorkingDir = '' +FSType = '' +CleanTest = True + +#initialize checks if there is a config file, and reads it if it exists. If no config file exists, it creates one with default values. +def initialize(): + Config = ConfigParser.ConfigParser() + if os.path.isfile('config.ini'): + print('Config file found; reading values.') + Config.read('config.ini') + try: + global WorkingDir + WorkingDir = Config.get('Parameters','WorkingDir') + global FSType + FSType = Config.get('Parameters','FSType') + global CleanTest + CleanTest = Config.getboolean('Parameters','CleanTest') + except: + print('An exception occured while reading the config file.') + sys.exit() + print('Configuration loaded.') + return() + +#subprocess.check_call('python populate-conf.py', shell=True) + +initialize() + +#make sure blktrace isn't running +try: + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) +except Exception, e: + pass + +#mount fs +if FSType == 'betrfs': + subprocess.check_call( '../../setup-ftfs.sh', shell=True) +else: + subprocess.check_call( '../../setup-' + FSType +'.sh', shell=True) + +subprocess.check_call('sudo dovecot', shell=True) +#check if benchmark exists +#setup repos +if os.path.isdir('benchmark') == False: + subprocess.call('sudo bash mailserver-setupdir.sh', shell=True) + subprocess.call('sudo python mailserver-setup.py', shell=True) +else: + print 'copying benchmark dir over' + subprocess.call('cp -a benchmark/* /mnt/benchmark', shell=True) + subprocess.call('chown -R ftfstest1:ftfstest1 /mnt/benchmark/ftfstest1', shell=True) + subprocess.call('chown -R ftfstest2:ftfstest2 /mnt/benchmark/ftfstest2', shell=True) +#setup test always +subprocess.check_call('sudo python runtest.py ', shell=True) +#run cleantest.py +if CleanTest == True: + #mount clean fs + subprocess.check_call('python runcleantest.py', shell=True) +subprocess.check_call('sudo dovecot stop', shell=True) diff --git a/benchmarks/aging/mailserver/runcleantest.py b/benchmarks/aging/mailserver/runcleantest.py new file mode 100644 index 000000000..bd5286855 --- /dev/null +++ b/benchmarks/aging/mailserver/runcleantest.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +#test.py +#Improved version of the aging grep test with blktrace, backups, and config files. Running without a config file will generate one with default values. + +import time +import subprocess +import ConfigParser +import os.path +import sys +import json +import argparse + +#Global variables: parameters for the test. Assigned by initialize(). +WorkingDir = '' +WorkingPartition = '' +GREPRandom = '' +CheckoutsPerGREP = 0 +GREPsPerBackup = 0 +TotalCheckouts = 0 +FSType = '' +PreTestRemount = True +WriteAmpLength = 0 + +#initialize checks if there is a config file, and reads it if it exists. If no config file exists, it creates one with default values. +def initialize(): + Config = ConfigParser.ConfigParser() + if os.path.isfile('config.ini'): + print('Config file found; reading values.') + Config.read('config.ini') + try: + global WorkingDir + WorkingDir = Config.get('Parameters','WorkingDir') + global WorkingPartition + WorkingPartition = Config.get('Parameters','WorkingPartition') + global GREPRandom + GREPRandom = Config.get('Parameters','GREPRandom') + global CheckoutsPerGREP + CheckoutsPerGREP = Config.getint('Parameters','CheckoutsPerGREP') + global TotalCheckouts + TotalCheckouts = Config.getint('Parameters','TotalCheckouts') + global FSType + FSType = Config.get('Parameters','FSType') + global PreTestRemount + PreTestRemount = Config.getboolean('Parameters','PreTestRemount') + global WriteAmpLength + WriteAmpLength = Config.getint('Parameters','WriteAmpLength') + except: + print('An exception occured while reading the config file.') + sys.exit() + print('Configuration loaded.') + +def cleangreptest(testno): + subprocess.check_call('rm -rf *', cwd='clean_temp', shell=True) + subprocess.check_call('cp -a ' + WorkingDir + '/* clean_temp', shell=True) + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + if FSType == 'betrfs': + subprocess.check_call( '../../setup-ftfs.sh', shell=True) + else: + subprocess.check_call( '../../setup-' + FSType + '.sh', shell=True) + subprocess.check_call('cp -a clean_temp/* ' + WorkingDir, shell=True) + if(PreTestRemount): + if(FSType=='betrfs'): + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call( '../../mount-ftfs.sh' , shell=True) + elif(FSType=='zfs'): + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.check_call( 'umount ' + WorkingDir, shell=True) + subprocess.check_call('zfs mount -a', shell=True) + else: + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call('mount ' + WorkingPartition + ' ' + WorkingDir, shell=True) + else: + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.call('blktrace -a read -d ' + WorkingPartition.rstrip('0123456789') + ' -o traces/cleantrace' + str(testno).zfill(6) + ' &', shell=True) + start = time.time() + subprocess.call('(grep -r --binary-files=text "' + GREPRandom + '" ' + WorkingDir +') > /dev/null', stderr=subprocess.STDOUT, shell=True) + stop = time.time() + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) + return (stop - start) + +################################################################################## +# Main Script Begins Here + +initialize() +results= [] + +for i in range(100): + subprocess.check_call('sudo python mailserver-aging.py', shell=True) + print('Running clean grep test: ' + str(i)) + thisgrep = cleangreptest(i) + print('clean grep test completed in ' + str(thisgrep) + ' seconds') + results.append(thisgrep) + with open('cleanresults.json','w') as outfile: + json.dump(results, outfile) + if(PreTestRemount): + if(FSType=='betrfs'): + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call( '../../mount-ftfs.sh' , shell=True) + elif(FSType=='zfs'): + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.check_call( 'umount ' + WorkingDir, shell=True) + subprocess.check_call('zfs mount -a', shell=True) + else: + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call('mount ' + WorkingPartition + ' ' + WorkingDir, shell=True) + else: + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + time.sleep(1) + subprocess.call('blktrace -a write -d ' + WorkingPartition.rstrip('0123456789') + ' -o traces/cleanwritetrace' + str(i).zfill(6) + ' &', shell=True) + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) + time.sleep(1) + +try: + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) +except Exception, e: + pass diff --git a/benchmarks/aging/mailserver/runtest.py b/benchmarks/aging/mailserver/runtest.py new file mode 100644 index 000000000..3461fadce --- /dev/null +++ b/benchmarks/aging/mailserver/runtest.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +#test.py +#Improved version of the aging grep test with blktrace, backups, and config files. Running without a config file will generate one with default values. + +import time +import subprocess +from subprocess import CalledProcessError +import ConfigParser +import os.path +import sys +import json +import argparse + +#Global variables: parameters for the test. Assigned by initialize(). +WorkingDir = '' +WorkingPartition = '' +GREPRandom = '' +CheckoutsPerGREP = 0 +#GREPsPerBackup = 0 +TotalCheckouts = 0 +#BackupDir = '' +#BackupLast = False +FSType = '' +PreTestRemount = True +FTIndex = '' +WriteAmpLength = 0 + +#initialize checks if there is a config file, and reads it if it exists. If no config file exists, it creates one with default values. +def initialize(): + Config = ConfigParser.ConfigParser() + if os.path.isfile('config.ini'): + print('Config file found; reading values.') + Config.read('config.ini') + try: + global WorkingDir + WorkingDir = Config.get('Parameters','WorkingDir') + global WorkingPartition + WorkingPartition = Config.get('Parameters','WorkingPartition') + global GREPRandom + GREPRandom = Config.get('Parameters','GREPRandom') + global CheckoutsPerGREP + CheckoutsPerGREP = Config.getint('Parameters','CheckoutsPerGREP') +# global GREPsPerBackup +# GREPsPerBackup = Config.getint('Parameters','GREPsPerBackup') + global TotalCheckouts + TotalCheckouts = Config.getint('Parameters','TotalCheckouts') +# global BackupDir +# BackupDir = Config.get('Parameters','BackupDir') +# global BackupLast +# BackupLast = Config.getboolean('Parameters','BackupLast') + global FSType + FSType = Config.get('Parameters','FSType') + global PreTestRemount + PreTestRemount = Config.getboolean('Parameters','PreTestRemount') + global WriteAmpLength + WriteAmpLength = Config.getint('Parameters','WriteAmpLength') + except: + print('An exception occured while reading the config file.') + sys.exit() + print('Configuration loaded.') + +#greptest: runs a wall-timed test of how long it takes to grep a fixed random stripng recursively through the research directory. testno is used to distinguish the traces. +def greptest(testno): + if(PreTestRemount): + if(FSType=='betrfs'): + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call( '../../mount-ftfs.sh' , shell=True) + elif(FSType=='zfs'): + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.check_call( 'umount ' + WorkingDir, shell=True) + subprocess.check_call('zfs mount -a', shell=True) + else: + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call('mount ' + WorkingPartition + ' ' + WorkingDir, shell=True) + else: + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.call('blktrace -a read -d ' + WorkingPartition.rstrip('0123456789') + ' -o traces/trace' + str(testno).zfill(6) + ' &', shell=True) + start = time.time() + subprocess.call('(grep -r --binary-files=text "' + GREPRandom + '" ' + WorkingDir + ') > /dev/null', stderr=subprocess.STDOUT, shell=True) + stop = time.time() + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) + return (stop - start) + + +################################################################################## +# Main Script Begins Here + +initialize() + +results =[] + +for i in range(100): + subprocess.call('python mailserver-aging.py', shell=True) + print('Running grep test: ' + str(i)) + fssize = subprocess.check_output('du -s', shell=True, cwd=WorkingDir) + thisgrep = greptest(i) + print('grep test completed in ' + str(thisgrep) + ' seconds') + results.append((int(fssize.split('\t', 1)[0]), thisgrep)) + with open('results.json','w') as outfile: + json.dump(results, outfile) + if(PreTestRemount): + if(FSType=='betrfs'): + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call( '../../mount-ftfs.sh' , shell=True) + elif(FSType=='zfs'): + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + subprocess.check_call( 'umount ' + WorkingDir, shell=True) + subprocess.check_call('zfs mount -a', shell=True) + else: + subprocess.check_call( '../../cleanup-fs.sh' , shell=True) + subprocess.check_call('mount ' + WorkingPartition + ' ' + WorkingDir, shell=True) + else: + subprocess.call('free && sync && echo 3 > /proc/sys/vm/drop_caches && free', shell=True) + time.sleep(1) + subprocess.call('blktrace -a write -d ' + WorkingPartition.rstrip('0123456789') + ' -o traces/writetrace' + str(i/CheckoutsPerGREP).zfill(6) + ' &', shell=True) + time.sleep(1) + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) + time.sleep(1) + +try: + subprocess.call('kill -15 ' + subprocess.check_output(["pidof","-s","blktrace"]), shell=True) +except Exception, e: + pass diff --git a/benchmarks/micro/large-file/random_write.c b/benchmarks/micro/large-file/random_write.c index 86936b9c1..6a20e9e4e 100644 --- a/benchmarks/micro/large-file/random_write.c +++ b/benchmarks/micro/large-file/random_write.c @@ -2,12 +2,14 @@ #include #include #include +#include #include #include #include #include -static long randomwrites = 10000; + +static long randomwrites = 32 * (256 * 1024); static char * fname = NULL; static long long fsize = 0; static char * prog_name; @@ -19,7 +21,7 @@ int main(int argc, char* argv[]) { int pos; int fd; int i; - long long *array; + long long *array; char buffer[4] = {'\20','\10','\5','W'}; @@ -35,7 +37,7 @@ int main(int argc, char* argv[]) { return -1; } - array = malloc(sizeof(int) * randomwrites); + array = malloc(sizeof(long long) * randomwrites); if (random == NULL) { fprintf(stderr, "Allocate memory failed\n"); return -1; @@ -46,7 +48,7 @@ int main(int argc, char* argv[]) { for (i = 0; i < randomwrites; i++) { array[i] = (random()<<32|random()) % (fsize - 4); } - + if((fd = open(fname, O_RDWR,0644)) < 0) { fprintf(stderr, "open file failed\n"); return -1; @@ -106,4 +108,3 @@ void process_options(int argc, char * argv[]){ } } - diff --git a/benchmarks/micro/large-file/sequential_write.c b/benchmarks/micro/large-file/sequential_write.c index 274508a57..e0f925340 100644 --- a/benchmarks/micro/large-file/sequential_write.c +++ b/benchmarks/micro/large-file/sequential_write.c @@ -23,12 +23,13 @@ static unsigned int rand_blocks = RAND_BLOCKS; static void process_options(int, char *[]); int main(int argc, char* argv[]) { - struct timespec start, end; + struct timespec start, end, gb_start, gb_end; double elapsed, mb; long long pos; int fd; int ret; int i, j; + unsigned long nr_gb; char **array; prog_name = argv[0]; @@ -71,31 +72,52 @@ int main(int argc, char* argv[]) { } clock_gettime(CLOCK_MONOTONIC, &start); + clock_gettime(CLOCK_MONOTONIC, &gb_start); i = 0; pos = 0; + nr_gb = 1; for(pos = 0; pos < fsize; pos += block_size) { ret = pwrite(fd, array[i], block_size, pos); if (ret != block_size) printf("short write (ret: %d)\n", ret); i = (i+1) % rand_blocks; + + { + unsigned long gb = nr_gb << 30; + + if (gb >= pos && (pos + block_size) >= gb) { + clock_gettime(CLOCK_MONOTONIC, &gb_end); + elapsed = (gb_end.tv_sec - gb_start.tv_sec) + + (gb_end.tv_nsec - gb_start.tv_nsec) / 1000000000.0; + printf("%lu GB\n", nr_gb); + printf("write, seq, %lf, %lf, %lf\n", 1024.0, elapsed, 1024.0 / elapsed); + gb_start = gb_end; + nr_gb++; + } + } } - fsync(fd); - clock_gettime(CLOCK_MONOTONIC, &end); + { + clock_gettime(CLOCK_MONOTONIC, &end); + elapsed = (end.tv_sec - start.tv_sec) + + (end.tv_nsec - start.tv_nsec) / 1000000000.0; + printf("before fsync: write, seq, %lf, %lf, %lf\n", fsize/1.0E6, elapsed, (fsize/1.0E6) / elapsed); + } + fsync(fd); + clock_gettime(CLOCK_MONOTONIC, &end); close(fd); elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1000000000.0; - mb = fsize/1.0E6; printf("op, seq.or.rand, size.MB, time.s, throughput.MBps\n"); printf("write, seq, %lf, %lf, %lf\n", mb, elapsed, mb / elapsed); - return 0; } + void print_usage (FILE * stream){ fprintf(stream, "%s -s FILESIZE -f FNAME [-r RANDOMWRITES]\n", prog_name); fprintf(stream, "\t -r --random_seed seed for srand()\n"); diff --git a/filesystem/Makefile b/filesystem/Makefile index 65d818359..ce0c3f06b 100644 --- a/filesystem/Makefile +++ b/filesystem/Makefile @@ -29,9 +29,14 @@ ftfs-objs := \ toku_memleak_detect.o \ toku_zlib.o \ libftindex.o \ - ftfs_toku_lock.o + ftfs_toku_lock.o \ + ftfs_profile.o KBUILD_CFLAGS += -DFTFS_SHORT_BLOCK +#KBUILD_CFLAGS += -DFTFS_PROFILE_UNLINK +#KBUILD_CFLAGS += -DFTFS_PROFILE_RMDIR +KBUILD_CFLAGS += -DFTFS_PROFILE_EVICT +#KBUILD_CFLAGS += -DFTFS_PROFILE_DESTROY #KBUILD_CFLAGS += -DFTFS_DEBUG #-DSOUTHBOUND_DEBUG #-DFTFS_MEM_DEBUG # -DFTFS_DEBUG_PTRS #include $(PWD)/.turnoff-opts.mkinclude diff --git a/filesystem/ftfs_module.c b/filesystem/ftfs_module.c index 4d84676b6..314481af7 100644 --- a/filesystem/ftfs_module.c +++ b/filesystem/ftfs_module.c @@ -27,6 +27,7 @@ #include "toku_checkpoint.h" #include "toku_flusher.h" #include "toku_memleak_detect.h" +#include "ftfs_profile.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stony Brook University"); @@ -82,6 +83,7 @@ static void __exit ftfs_module_exit(void) TOKU_MEMLEAK_EXIT; toku_engine_status_exit(); + ftfs_profile_exit(); toku_checkpoint_exit(); toku_flusher_exit(); printf_count_blindwrite(); @@ -107,6 +109,8 @@ static int __init ftfs_module_init(void) int ret; void *data = NULL; + trace_printk("ftfs_module_init is called!\n"); + if (!sb_dev) { ftfs_error(__func__, "no mount device for ftfs_southbound!"); return -EINVAL; @@ -166,6 +170,12 @@ static int __init ftfs_module_init(void) return ret; } + ret = ftfs_profile_init(); + if (ret) { + ftfs_error(__func__, "can't init ftfs profile proc"); + return ret; + } + ret = toku_checkpoint_init(); if (ret) { ftfs_error(__func__, "can't init toku checkpoint proc"); diff --git a/filesystem/ftfs_profile.c b/filesystem/ftfs_profile.c new file mode 100644 index 000000000..ec3769dca --- /dev/null +++ b/filesystem/ftfs_profile.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include "ftfs_fs.h" +#include "ftfs_profile.h" + +static struct proc_dir_entry * ftfs_profile_entry; + +static void ftfs_print_unlink_profile(void) +{ + printk("===== unlink =====\n"); + printk("time of if branch:%lld\n", unlink_stat.stage1_if.tv64); + printk("time of else branch:%lld\n", unlink_stat.stage1_else.tv64); + printk("time of stage2:%lld\n", unlink_stat.stage2.tv64); + printk("time of ftfs_unlink:%lld\n", unlink_stat.stage2.tv64 + + unlink_stat.stage1_else.tv64 + + unlink_stat.stage1_if.tv64); + printk("time of ftfs_rmdir:%lld\n", unlink_stat.rmdir.tv64); + printk("time of ftfs_destroy_inode:%lld\n", unlink_stat.destroy_inode.tv64); + printk("time of ftfs_evict_inode:%lld\n", unlink_stat.evict_inode.tv64); + printk("count of if branch:%u\n", unlink_stat.count_if); + printk("count of else branch:%u\n", unlink_stat.count_else); + printk("count of ftfs_rmdir:%u\n", unlink_stat.count_rmdir); + printk("count of ftfs_destroy_inode:%u\n", unlink_stat.count_destroy); + printk("count of ftfs_evict_inode:%u\n", unlink_stat.count_evict); + printk("===== end ======\n"); + memset(&unlink_stat, 0, sizeof(unlink_stat)); +} + +static void ftfs_print_unlink_clean_profile(void) +{ + memset(&unlink_stat, 0, sizeof(unlink_stat)); +} + +static ssize_t ftfs_read_profile_proc(struct file *file, char __user *buf, + size_t count, loff_t *off) +{ + return 0; +} + +static ssize_t ftfs_write_profile_proc(struct file *file, + const char __user *buffer, + size_t count, loff_t *offp) +{ + int i, ret; + char *buf; + + buf = kmalloc(count+1, GFP_KERNEL); + + if (!buf) { + ftfs_error(__func__, "ftfs_write_profile_proc: out of memory"); + return -ENOMEM; + } + + ret = copy_from_user(buf, buffer, count); + if (ret) { + ftfs_error(__func__, "ftfs_write_profile_proc: bad buffer"); + goto out; + } + + for (i = 0; i < count; i++) { + if (buf[i] == '\n') { + buf[i] = '\0'; + break; + } + } + + buf[count] = '\0'; + + if (0 == strcmp(buf, "unlink")) { + ftfs_print_unlink_profile(); + } + + if (0 == strcmp(buf, "unlink_clean")) { + ftfs_print_unlink_clean_profile(); + } + + + + + ret = count; + +out: + kfree(buf); + return ret; +} + +const struct file_operations ftfs_proc_profile_fops = { + .read = ftfs_read_profile_proc, + .write = ftfs_write_profile_proc, +}; + +int ftfs_profile_init(void) { + ftfs_profile_entry = proc_create(FTFS_PROFILE_PROC, 0666, NULL, + &ftfs_proc_profile_fops); + + if (ftfs_profile_entry == NULL) { + remove_proc_entry(FTFS_PROFILE_PROC, NULL); + ftfs_error(__func__, "Failed to init profile proc file: %s", + FTFS_PROFILE_PROC); + return -ENOMEM; + } + + ftfs_log(__func__, "ftfs profile procfs entry created"); + + return 0; +} + +void ftfs_profile_exit(void) { + remove_proc_entry(FTFS_PROFILE_PROC, NULL); + ftfs_log(__func__, "toku procfs entry removed"); +} diff --git a/filesystem/ftfs_profile.h b/filesystem/ftfs_profile.h new file mode 100644 index 000000000..c524b7311 --- /dev/null +++ b/filesystem/ftfs_profile.h @@ -0,0 +1,30 @@ +#ifndef FTFS_PROFILE_H +#define FTFS_PROFILE_H + +#include + + +#define FTFS_PROFILE_PROC "ftfs_profile" + +int ftfs_profile_init(void); +void ftfs_profile_exit(void); + +struct ftfs_unlink_stat { + ktime_t stage1_if; + ktime_t stage1_else; + ktime_t stage2; + ktime_t rmdir; + ktime_t destroy_inode; + ktime_t evict_inode; + + unsigned int count_if; + unsigned int count_else; + unsigned int count_rmdir; + unsigned int count_destroy; + unsigned int count_evict; +}; + +extern struct ftfs_unlink_stat unlink_stat; + + +#endif /* FTFS_PROFILE_H */ diff --git a/ftfs/blkio/Makefile b/ftfs/blkio/Makefile deleted file mode 100644 index 059aba7cc..000000000 --- a/ftfs/blkio/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -DEBUG = 0 - -EXTRA_CFLAGS += -I$(PWD)/include - -#ifeq ($(DEBUG),1) -# EXTRA_CFLAGS += -DCONFIG_QUOTIENT_FILTER_DEBUG -#endif - -# If KERNELRELEASE is defined, we've been invoked from the -# kernel build system and can use its language. -ifneq ($(KERNELRELEASE),) - obj-m := block_dev.o block_dev_test.o -# Otherwise we were called directly from the command -# line; invoke the kernel build system. -else - KERNELDIR ?= /lib/modules/$(shell uname -r)/build - PWD := $(shell pwd) - -default: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules - -clean: - $(MAKE) -C $(KERNELDIR) M=$(PWD) clean - -endif diff --git a/ftfs/blkio/README b/ftfs/blkio/README deleted file mode 100644 index e69de29bb..000000000 diff --git a/ftfs/blkio/bdev.sh b/ftfs/blkio/bdev.sh deleted file mode 100755 index 9fd9929d3..000000000 --- a/ftfs/blkio/bdev.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -make DEBUG=1 -sudo rmmod block_dev_test -sudo rmmod block_dev -sudo insmod block_dev.ko -sudo insmod block_dev_test.ko - -#num_tests=8 -#for ((i=1; i<=$num_tests; ++i )) -#do -# testcase="/proc/quotient_filter/"$i -# cat $testcase -#done diff --git a/ftfs/blkio/block_dev.c b/ftfs/blkio/block_dev.c deleted file mode 100644 index 00abf3467..000000000 --- a/ftfs/blkio/block_dev.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -struct page* bd_get_page(struct block_device *bdev, pgoff_t index) -{ - struct inode *bd_inode = bdev->bd_inode; - struct address_space *mapping = bd_inode->i_mapping; - struct page *page; - int error; - - BUG_ON(!mapping); - - page = find_or_create_page(mapping, index, mapping_gfp_mask(mapping)); - if( !PageUptodate(page) ) - { - error = mapping->a_ops->readpage(NULL, page); - BUG_ON(error); - lock_page(page); - } - - return page; -} - -void bd_put_page(struct page *page) -{ - if(PageLocked(page)) - unlock_page(page); - page_cache_release(page); -} - -int bd_read_block_from_disk(struct block_device *bdev, pgoff_t index, void *dst) -{ - struct page *page; - void *src; - - if (!dst) - return -EINVAL; - - page = bd_get_page(bdev, index); - src = kmap(page); - if (!src) - return -EINVAL; - - memcpy(dst, src, PAGE_SIZE); - kunmap(page); - bd_put_page(page); - - return 0; -} -EXPORT_SYMBOL(bd_read_block_from_disk); - -int bd_write_block_to_disk(struct block_device *bdev, pgoff_t index, void *src) -{ - struct page *page = NULL; - loff_t pos; - int error; - void *fs_data = NULL; - void *dst; - struct address_space *mapping = bdev->bd_inode->i_mapping; - - if (!src) - return -EINVAL; - - pos = index << PAGE_CACHE_SHIFT; - error = mapping->a_ops->write_begin(NULL, mapping, pos, - PAGE_CACHE_SIZE, AOP_FLAG_UNINTERRUPTIBLE, &page, &fs_data); - BUG_ON(error); - dst = kmap(page); - if (!dst) - return -EINVAL; - - memcpy(dst, src, PAGE_SIZE); - kunmap(page); - error = mapping->a_ops->write_end(NULL, mapping, pos, PAGE_CACHE_SIZE, - PAGE_CACHE_SIZE, page, fs_data); - BUG_ON(error != PAGE_CACHE_SIZE); - - return 0; -} -EXPORT_SYMBOL(bd_write_block_to_disk); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("Quotient Filter"); diff --git a/ftfs/blkio/block_dev_test.c b/ftfs/blkio/block_dev_test.c deleted file mode 100644 index 3a0da9230..000000000 --- a/ftfs/blkio/block_dev_test.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Test Suite of FTFS bdev functionality - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BDEV_NAME "/dev/loop0" -#define BDEV_MODE (FMODE_READ|FMODE_WRITE) - -extern int bd_write_block_to_disk(struct block_device *bdev, pgoff_t index, void *src); -extern int bd_read_block_from_disk(struct block_device *bdev, pgoff_t index, void *dst); - -int test1(char *buf, char **start, off_t offset, int count, int *eof, - void *data) -{ - struct block_device *bdev; - - bdev = blkdev_get_by_path(BDEV_NAME, BDEV_MODE, NULL); - if(IS_ERR(bdev)) - { - printk("Cannot open block device for CF\n"); - return -EFAULT; - } - - blkdev_put(bdev, BDEV_MODE); - - printk(KERN_INFO "BDEV test 1 succeeded\n"); - return 0; -} - -int test2(char *buf, char **start, off_t offset, int count, int *eof, - void *data) -{ - struct block_device *bdev; - int ret = 0; - void *bytes; - - bdev = blkdev_get_by_path(BDEV_NAME, BDEV_MODE, NULL); - if(IS_ERR(bdev)) - { - printk("Cannot open block device for CF\n"); - return -EFAULT; - } - - bytes = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!bytes) - return -ENOMEM; - - memset(bytes, 'J', PAGE_SIZE); - - if ((ret = bd_write_block_to_disk(bdev, 0, bytes))) - goto out; - - blkdev_put(bdev, BDEV_MODE); - -out: - kfree(bytes); - printk(KERN_INFO "BDEV test 2 succeeded\n"); - return ret; -} - -int test3(char *buf, char **start, off_t offset, int count, int *eof, - void *data) -{ - struct block_device *bdev; - int ret = 0; - void *bytes; - - bdev = blkdev_get_by_path(BDEV_NAME, BDEV_MODE, NULL); - if(IS_ERR(bdev)) - { - printk("Cannot open block device for CF\n"); - return -EFAULT; - } - - bytes = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!bytes) - return -ENOMEM; - - if ((ret = bd_read_block_from_disk(bdev, 0, bytes))) - goto out; - - printk(KERN_INFO "First byte is %c\n", ((char*)bytes)[0]); - - blkdev_put(bdev, BDEV_MODE); - -out: - kfree(bytes); - printk(KERN_INFO "BDEV test 3 succeeded\n"); - return ret; -} - -static struct proc_dir_entry *dir; - -static int cf_test_module_init(void) -{ - struct proc_dir_entry *entry; - - dir = proc_mkdir("ftst_bdev", NULL); - - entry = create_proc_entry("1", 0666, dir); - entry->read_proc = test1; - entry = create_proc_entry("2", 0666, dir); - entry->read_proc = test2; - entry = create_proc_entry("3", 0666, dir); - entry->read_proc = test3; - - return 0; -} - -static void cf_test_module_exit(void) -{ - remove_proc_entry("1", dir); - remove_proc_entry("2", dir); - remove_proc_entry("3", dir); - remove_proc_entry("cascade_filter", NULL); -} - -module_init(cf_test_module_init); -module_exit(cf_test_module_exit); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("Cascade Filter Test Suite"); diff --git a/ftfs/blkio/commit_email b/ftfs/blkio/commit_email deleted file mode 100644 index 01b850792..000000000 --- a/ftfs/blkio/commit_email +++ /dev/null @@ -1 +0,0 @@ -porter@cs.stonybrook.edu,vakulkarni@cs.stonybrook.edu,yazhan@cs.stonybrook.edu,ysourabh@cs.stonybrook.edu diff --git a/ftfs/blkio/include/linux/block_dev.h b/ftfs/blkio/include/linux/block_dev.h deleted file mode 100644 index e0f7590e1..000000000 --- a/ftfs/blkio/include/linux/block_dev.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include -#include -#include -#include - diff --git a/ftfs/ftfs_error.c b/ftfs/ftfs_error.c index 3aaa886c9..9a14371fd 100644 --- a/ftfs/ftfs_error.c +++ b/ftfs/ftfs_error.c @@ -1,6 +1,9 @@ #include #include +#include +#include #include "ftfs_pthread.h" + #include "ftfs.h" extern char *strerror(int e); @@ -32,3 +35,15 @@ void perror(const char *s) printk(KERN_ALERT "%s\n", s); printk(KERN_ALERT ": %s\n", strerror(e)); } + +void print_day_time(void) +{ + struct timeval time; + unsigned long local_time; + struct rtc_time tm; + + do_gettimeofday(&time); + local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + trace_printk(" @ (%04d-%02d-%02d %02d:%02d:%02d)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); +} diff --git a/ftfs/ftfs_error.h b/ftfs/ftfs_error.h index a2040d6ef..1d7237aab 100644 --- a/ftfs/ftfs_error.h +++ b/ftfs/ftfs_error.h @@ -8,4 +8,5 @@ void set_errno(int ret); int get_errno(void); void perror(const char *s); +void print_day_time(void); #endif diff --git a/ftfs_fs/ftfs_super.c b/ftfs_fs/ftfs_super.c index d34f15dd2..153a9c566 100644 --- a/ftfs_fs/ftfs_super.c +++ b/ftfs_fs/ftfs_super.c @@ -10,6 +10,7 @@ #include #include "ftfs_fs.h" +#include "ftfs_profile.h" #define DCACHE_FTFS_FLAG 0x04000000 @@ -214,6 +215,7 @@ static inline int ftfs_get_read_trylock(struct ftfs_inode *f_inode) return down_read_trylock(&f_inode->key_lock); } + static inline void ftfs_put_read_lock(struct ftfs_inode *f_inode) { up_read(&f_inode->key_lock); @@ -463,6 +465,7 @@ static int split_circle(struct dentry *dentry) LIST_HEAD(locked_children); DB_TXN *txn; + trace_printk("split_circle is called\n"); old_meta_key = ftfs_get_write_lock(FTFS_I(inode)); if (meta_key_is_circle_root(old_meta_key)) { ftfs_put_write_lock(FTFS_I(inode)); @@ -862,12 +865,7 @@ ftfs_writepage(struct page *page, struct writeback_control *wbc) struct ftfs_sb_info *sbi = inode->i_sb->s_fs_info; DB_TXN *txn; - ret = ftfs_get_read_trylock(FTFS_I(inode)); - if (!ret) - return AOP_FTFS_WRITEPAGE; - else - meta_key = FTFS_I(inode)->key; - + meta_key = ftfs_get_read_lock(FTFS_I(inode)); set_page_writeback(page); TXN_GOTO_LABEL(retry); ftfs_bstore_txn_begin(sbi->db_env, NULL, &txn, TXN_MAY_WRITE); @@ -961,8 +959,13 @@ __ftfs_writepages_write_pages(struct ftfs_writepages_vec *writepages_vec, unsigned offset; char *buf; struct page *page; + struct ftfs_meta_key *meta_key; DB_TXN *txn; + meta_key = ftfs_get_read_lock(FTFS_I(inode)); + if (unlikely(meta_key->circle_id != data_key->circle_id || + strcmp(meta_key->path, data_key->path) != 0)) + copy_data_key_from_meta_key(data_key, meta_key, 0); retry: i_size = i_size_read(inode); end_index = i_size >> PAGE_CACHE_SHIFT; @@ -990,6 +993,7 @@ __ftfs_writepages_write_pages(struct ftfs_writepages_vec *writepages_vec, ret = ftfs_bstore_txn_commit(txn, DB_TXN_NOSYNC); COMMIT_JUMP_ON_CONFLICT(ret, retry); out: + ftfs_put_read_lock(FTFS_I(inode)); for (i = 0; i < writepages_vec->nr_pages; i++) { page = writepages_vec->pages[i]; end_page_writeback(page); @@ -1089,11 +1093,14 @@ static int ftfs_writepages(struct address_space *mapping, meta_key = ftfs_get_read_lock(FTFS_I(inode)); } } - data_key = alloc_data_key_from_meta_key(meta_key, 0); + data_key = kmalloc(DATA_KEY_MAX_LEN, GFP_KERNEL); if (!data_key) { + ftfs_put_read_lock(FTFS_I(inode)); ret = -ENOMEM; goto out; } + copy_data_key_from_meta_key(data_key, meta_key, 0); + ftfs_put_read_lock(FTFS_I(inode)); while (!done && (index <= end)) { nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); @@ -1176,8 +1183,6 @@ static int ftfs_writepages(struct address_space *mapping, free_dkey_out: kfree(data_key); out: - ftfs_put_read_lock(FTFS_I(inode)); - if (!cycled && !done) { cycled = 1; index = 0; @@ -1614,6 +1619,9 @@ static int ftfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) static int ftfs_rmdir(struct inode *dir, struct dentry *dentry) { +#ifdef FTFS_PROFILE_RMDIR + ktime_t rmdir_start = ktime_get(); +#endif int r, ret; struct inode *inode = dentry->d_inode; struct ftfs_sb_info *sbi = inode->i_sb->s_fs_info; @@ -1681,7 +1689,11 @@ static int ftfs_rmdir(struct inode *dir, struct dentry *dentry) if (!ret) ftfs_update_nr_inode(dir, -1, 0, 0); - +#ifdef FTFS_PROFILE_RMDIR + unlink_stat.rmdir = ktime_add(unlink_stat.rmdir, + ktime_sub(ktime_get(), rmdir_start)); + unlink_stat.count_rmdir += 1; +#endif return ret; } @@ -1828,12 +1840,18 @@ static int ftfs_link(struct dentry *old_dentry, return ret; } +struct ftfs_unlink_stat unlink_stat; + static int ftfs_unlink(struct inode *dir, struct dentry *dentry) { int ret = 0; struct inode *inode = dentry->d_inode; struct ftfs_meta_key *dir_meta_key, *meta_key; - +#ifdef FTFS_PROFILE_UNLINK + ktime_t stage1_start; + ktime_t stage2_start; + stage1_start = ktime_get(); +#endif dir_meta_key = ftfs_get_read_lock(FTFS_I(dir)); meta_key = ftfs_get_read_lock(FTFS_I(inode)); @@ -1863,15 +1881,28 @@ static int ftfs_unlink(struct inode *dir, struct dentry *dentry) ftfs_put_read_lock(FTFS_I(dir)); if (!ret) ftfs_update_nr_inode(dir, -1, 0, 0); +#ifdef FTFS_PROFILE_UNLINK + unlink_stat.stage1_if = ktime_add(unlink_stat.stage1_if, + ktime_sub(ktime_get(), stage1_start)); + unlink_stat.count_if += 1; +#endif } else { ftfs_put_read_lock(FTFS_I(inode)); ftfs_put_read_lock(FTFS_I(dir)); ftfs_update_nr_inode(dir, -1, -FTFS_I(inode)->nr_data, 0); + +#ifdef FTFS_PROFILE_UNLINK + unlink_stat.stage1_else = ktime_add(unlink_stat.stage1_else, + ktime_sub(ktime_get(), stage1_start)); + unlink_stat.count_else += 1; +#endif } if (ret) return ret; - +#ifdef FTFS_PROFILE_UNLINK + stage2_start = ktime_get(); +#endif drop_nlink(inode); mark_inode_dirty(inode); @@ -1885,6 +1916,10 @@ static int ftfs_unlink(struct inode *dir, struct dentry *dentry) printk("%s dentry ref count %d\n", __func__, dentry->d_lockref.count); } +#ifdef FTFS_PROFILE_UNLINK + unlink_stat.stage2 = ktime_add(unlink_stat.stage2, + ktime_sub(ktime_get(), stage2_start)); +#endif return ret; } @@ -2137,13 +2172,21 @@ static struct inode *ftfs_alloc_inode(struct super_block *sb) static void ftfs_destroy_inode(struct inode *inode) { struct ftfs_inode *ftfs_inode = FTFS_I(inode); - +#ifdef FTFS_PROFILE_DESTROY + ktime_t destroy_start = ktime_get(); +#endif ftfs_get_write_lock(ftfs_inode); if (ftfs_inode->key != &root_dir_meta_key) meta_key_free(ftfs_inode->key); ftfs_inode->key = NULL; kmem_cache_free(ftfs_inode_cachep, ftfs_inode); + +#ifdef FTFS_PROFILE_DESTROY + unlink_stat.destroy_inode = ktime_add(unlink_stat.destroy_inode, + ktime_sub(ktime_get(), destroy_start)); + unlink_stat.count_destroy += 1; +#endif } static int @@ -2192,7 +2235,9 @@ static void ftfs_evict_inode(struct inode *inode) struct ftfs_meta_key *meta_key; struct ftfs_inode *ftfs_inode = FTFS_I(inode); DB_TXN *txn; - +#ifdef FTFS_PROFILE_EVICT + ktime_t evict_start = ktime_get(); +#endif if (inode->i_nlink) goto no_delete; @@ -2222,6 +2267,11 @@ static void ftfs_evict_inode(struct inode *inode) invalidate_inode_buffers(inode); clear_inode(inode); +#ifdef FTFS_PROFILE_EVICT + unlink_stat.evict_inode = ktime_add(unlink_stat.evict_inode, + ktime_sub(ktime_get(), evict_start)); + unlink_stat.count_evict += 1; +#endif } // called when VFS wishes to free sb (unmount), sync southbound here @@ -2594,10 +2644,10 @@ static void ftfs_kill_sb(struct super_block *sb) { sync_filesystem(sb); printk("dirty inode:\n"); - find_dirty_inodes(sb); + find_dirty_inodes(sb); kill_block_super(sb); printk("remaining inode:\n"); - find_remaining_inodes(sb); + find_remaining_inodes(sb); } static struct file_system_type ftfs_fs_type = { diff --git a/linux-3.11.10.diff b/linux-3.11.10.diff index 2c5cd9109..fe35bf859 100644 --- a/linux-3.11.10.diff +++ b/linux-3.11.10.diff @@ -1,6 +1,6 @@ diff -ru linux-3.11.10-orig/arch/x86/include/asm/page_64_types.h linux-3.11.10/arch/x86/include/asm/page_64_types.h --- linux-3.11.10-orig/arch/x86/include/asm/page_64_types.h 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/arch/x86/include/asm/page_64_types.h 2016-05-24 10:14:49.078980632 -0400 ++++ linux-3.11.10/arch/x86/include/asm/page_64_types.h 2016-02-13 17:20:55.178810833 -0500 @@ -1,7 +1,7 @@ #ifndef _ASM_X86_PAGE_64_DEFS_H #define _ASM_X86_PAGE_64_DEFS_H @@ -12,7 +12,7 @@ diff -ru linux-3.11.10-orig/arch/x86/include/asm/page_64_types.h linux-3.11.10/a diff -ru linux-3.11.10-orig/fs/direct-io.c linux-3.11.10/fs/direct-io.c --- linux-3.11.10-orig/fs/direct-io.c 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/fs/direct-io.c 2016-05-24 10:14:52.082980559 -0400 ++++ linux-3.11.10/fs/direct-io.c 2016-02-12 23:28:35.200314074 -0500 @@ -154,6 +154,43 @@ return sdio->tail - sdio->head; } @@ -84,7 +84,7 @@ diff -ru linux-3.11.10-orig/fs/direct-io.c linux-3.11.10/fs/direct-io.c struct page *page = ZERO_PAGE(0); diff -ru linux-3.11.10-orig/fs/fcntl.c linux-3.11.10/fs/fcntl.c --- linux-3.11.10-orig/fs/fcntl.c 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/fs/fcntl.c 2016-05-24 10:14:52.110980558 -0400 ++++ linux-3.11.10/fs/fcntl.c 2016-02-12 23:30:28.436311429 -0500 @@ -730,14 +730,15 @@ * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY * is defined as O_NONBLOCK on some platforms and not on others. @@ -103,20 +103,9 @@ diff -ru linux-3.11.10-orig/fs/fcntl.c linux-3.11.10/fs/fcntl.c )); fasync_cache = kmem_cache_create("fasync_cache", -diff -ru linux-3.11.10-orig/include/linux/fs.h linux-3.11.10/include/linux/fs.h ---- linux-3.11.10-orig/include/linux/fs.h 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/include/linux/fs.h 2016-05-24 10:14:52.286980554 -0400 -@@ -274,6 +274,7 @@ - enum positive_aop_returns { - AOP_WRITEPAGE_ACTIVATE = 0x80000, - AOP_TRUNCATED_PAGE = 0x80001, -+ AOP_FTFS_WRITEPAGE = 0x80002, - }; - - #define AOP_FLAG_UNINTERRUPTIBLE 0x0001 /* will not do a short write */ diff -ru linux-3.11.10-orig/include/uapi/asm-generic/fcntl.h linux-3.11.10/include/uapi/asm-generic/fcntl.h --- linux-3.11.10-orig/include/uapi/asm-generic/fcntl.h 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/include/uapi/asm-generic/fcntl.h 2016-05-24 10:14:52.414980551 -0400 ++++ linux-3.11.10/include/uapi/asm-generic/fcntl.h 2016-02-12 23:30:49.772310930 -0500 @@ -88,6 +88,11 @@ #define __O_TMPFILE 020000000 #endif @@ -129,34 +118,3 @@ diff -ru linux-3.11.10-orig/include/uapi/asm-generic/fcntl.h linux-3.11.10/inclu /* a horrid kludge trying to make sure that this will fail on old kernels */ #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) #define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT) -diff -ru linux-3.11.10-orig/lib/percpu_counter.c linux-3.11.10/lib/percpu_counter.c ---- linux-3.11.10-orig/lib/percpu_counter.c 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/lib/percpu_counter.c 2016-05-24 10:14:52.994980536 -0400 -@@ -80,8 +80,13 @@ - if (count >= batch || count <= -batch) { - raw_spin_lock(&fbc->lock); - fbc->count += count; -- raw_spin_unlock(&fbc->lock); -+ // dep 2/23/16: Backport a fix from 3/13. -+ // Zeroing the local counter without the lock held -+ // can cause sums of a series monotonic increments to -+ // decrease. The reader needs to wait for the local -+ // count to be zeroed. - __this_cpu_write(*fbc->counters, 0); -+ raw_spin_unlock(&fbc->lock); - } else { - __this_cpu_write(*fbc->counters, count); - } -diff -ru linux-3.11.10-orig/mm/vmscan.c linux-3.11.10/mm/vmscan.c ---- linux-3.11.10-orig/mm/vmscan.c 2013-11-29 13:42:37.000000000 -0500 -+++ linux-3.11.10/mm/vmscan.c 2016-05-24 10:14:53.014980536 -0400 -@@ -435,6 +435,9 @@ - return PAGE_ACTIVATE; - } - -+ if (res == AOP_FTFS_WRITEPAGE) -+ return PAGE_KEEP; -+ - if (!PageWriteback(page)) { - /* synchronous write or broken a_ops? */ - ClearPageReclaim(page);