-
-
Notifications
You must be signed in to change notification settings - Fork 605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement nvme driver #1284
Implement nvme driver #1284
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
conf_drivers_pci?=1 | ||
|
||
conf_drivers_nvme?=1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#ifndef BLK_IOCTL_H | ||
#define BLK_IOCTL_H | ||
|
||
#define _IOC_NRBITS 8 | ||
#define _IOC_TYPEBITS 8 | ||
#define _IOC_SIZEBITS 13 | ||
#define _IOC_DIRBITS 3 | ||
|
||
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) | ||
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) | ||
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) | ||
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) | ||
|
||
#define _IOC_NRSHIFT 0 | ||
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) | ||
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) | ||
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) | ||
|
||
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) | ||
#define _IOC_TYP(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) | ||
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) | ||
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) | ||
|
||
#define BLKGETSIZE64 114 | ||
#define BLKFLSBUF 97 | ||
#define BLKDISCARD 119 | ||
|
||
TRACEPOINT(trace_blk_ioctl, "dev=%s type=%#x nr=%d size=%d, dir=%d", char*, int, int, int, int); | ||
|
||
void no_bio_done(bio * b) {delete b;}; | ||
|
||
int | ||
blk_ioctl(struct device* dev, u_long io_cmd, void* buf) | ||
{ | ||
assert(dev); | ||
trace_blk_ioctl(dev->name, _IOC_TYP(io_cmd), _IOC_NR(io_cmd), _IOC_SIZE(io_cmd), _IOC_DIR(io_cmd)); | ||
|
||
switch (_IOC_NR(io_cmd)) { | ||
case BLKGETSIZE64: | ||
//device capacity in bytes | ||
*(off_t*) buf = dev->size; | ||
break; | ||
case BLKFLSBUF: { | ||
auto* bio = alloc_bio(); | ||
bio->bio_dev = dev; | ||
bio->bio_done = no_bio_done; | ||
bio->bio_cmd = BIO_FLUSH; | ||
|
||
dev->driver->devops->strategy(bio); | ||
} | ||
break; | ||
default: | ||
printf("ioctl not defined; type:%#x nr:%d size:%d, dir:%d\n",_IOC_TYP(io_cmd),_IOC_NR(io_cmd),_IOC_SIZE(io_cmd),_IOC_DIR(io_cmd)); | ||
return EINVAL; | ||
} | ||
return 0; | ||
} | ||
|
||
#endif |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please describe in comments what this test does and how one can run it? How different is it from various disk I/O-related tests located under I also suggest we move this to the |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#include "drivers/io-test.hh" | ||
#include <osv/contiguous_alloc.hh> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <random> | ||
#include <machine/atomic.h> | ||
#include <osv/clock.hh> | ||
|
||
volatile bool running; | ||
volatile u64 completed_io; | ||
volatile u64 requested_io; | ||
std::atomic<unsigned int> open_req; | ||
u32 max_open; | ||
u64 max_ios; | ||
|
||
void test_block_device(struct device *dev, int test_duration, int blcks_per_io, int blocksize, int blockshift) | ||
{ | ||
int report_step = 1e6; | ||
int io_size = blocksize * blcks_per_io; | ||
completed_io = 0; | ||
requested_io = 0; | ||
open_req.store(0); | ||
max_open = 64; | ||
max_ios = 1 << 30; | ||
|
||
printf("Start IO test dev : %s, IO size : %d\n",dev->name,io_size); | ||
sched::thread *t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of OSv internal API to create threads I would suggest using the standard |
||
t = sched::thread::make([dev,io_size,blockshift] { requesting(dev,io_size,blockshift);}, | ||
sched::thread::attr().name("IO_Test Request")); | ||
|
||
sched::thread *timer; | ||
timer = sched::thread::make([test_duration] { usleep(test_duration);}, | ||
sched::thread::attr().name("IO_Test_Timer")); | ||
|
||
sched::thread *repo; | ||
repo = sched::thread::make([test_duration,report_step,io_size] { reporting(test_duration,report_step,io_size);}, | ||
sched::thread::attr().name("IO_Test_Timer")); | ||
auto c = clock::get(); | ||
|
||
running = true; | ||
u64 start = c->time(); | ||
timer->start(); | ||
t->start(); | ||
repo->start(); | ||
|
||
timer->join(); | ||
running = false; | ||
u64 com = completed_io; | ||
u64 end = c->time(); | ||
int iops = (com * 1e9)/ (end - start); | ||
|
||
t->join(); | ||
repo->join(); | ||
printf("Test results runtime: %llu, completed IO : %llu, IOPS : %d\n",end-start,com,iops); | ||
} | ||
|
||
void reporting(int test_duration, int report_step, int io_size) { | ||
u32 prev_compl = completed_io; | ||
u32 compl_diff; | ||
u32 compl_tem; | ||
auto c = clock::get(); | ||
int time_diff; | ||
int time_tem; | ||
int prev_time = c->time(); | ||
while(running) { | ||
usleep(report_step); | ||
compl_tem = completed_io; | ||
time_tem = c->time(); | ||
|
||
compl_diff = compl_tem - prev_compl; | ||
prev_compl = compl_tem; | ||
time_diff = time_tem - prev_time; | ||
prev_time = time_tem; | ||
double iops = (compl_diff * 1e9 ) / (double) time_diff; | ||
|
||
printf("Timestep: %d, completed : %d, IOPS : %lf, open : %d\n",time_diff,compl_diff,iops,open_req.load()); | ||
} | ||
} | ||
|
||
|
||
void requesting(struct device *dev, u32 io_size, int blockshift) { | ||
void* buff; | ||
bio* bio; | ||
off_t max_blocks = dev->size >> blockshift; | ||
off_t max_offset = (max_blocks - 1) - (io_size >> blockshift); | ||
std::random_device rd; | ||
std::mt19937 gen(rd()); | ||
std::uniform_int_distribution<> distrib(0, max_offset); | ||
|
||
while(running) { | ||
if(requested_io >= max_ios ) | ||
break; | ||
|
||
buff = memory::alloc_phys_contiguous_aligned(io_size,2); | ||
assert(buff); | ||
memset(buff, 1, io_size); | ||
|
||
bio = alloc_bio(); | ||
bio->bio_dev = dev; | ||
bio->bio_data = buff; | ||
bio->bio_done = io_done; | ||
bio->bio_length = io_size; | ||
bio->bio_bcount = io_size; | ||
bio->bio_cmd = BIO_READ; | ||
|
||
bio->bio_offset = ((off_t) distrib(gen)) << blockshift; | ||
|
||
while(max_open<=open_req) { | ||
usleep(10); | ||
} | ||
open_req.fetch_add(1); | ||
atomic_add_64(&requested_io,1); | ||
dev->driver->devops->strategy(bio); | ||
} | ||
} | ||
|
||
void io_done(struct bio* bio) { | ||
|
||
if(bio->bio_flags != BIO_DONE) { | ||
printf("BIO_Error during IO Test: %x\n",bio->bio_flags); | ||
} | ||
u64 old = atomic_fetchadd_long(&completed_io, 1); | ||
|
||
open_req.fetch_add(-1); | ||
|
||
free(bio->bio_data); | ||
delete bio; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#ifndef IO_TEST_H | ||
#define IO_TEST_H | ||
|
||
#include <osv/device.h> | ||
#include <osv/bio.h> | ||
|
||
void requesting(struct device *dev, u32 io_size, int blocksize); | ||
void reporting(int test_duration, int report_step, int io_size); | ||
void io_done(struct bio* bio); | ||
void test_block_device(struct device *dev, int test_duration,int blcks_per_io, int blocksize=512, int blockshift=9); | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add a copyright statement to all your files (see this one for example -
osv/fs/rofs/rofs_cache.cc
Lines 1 to 7 in f11c021