Skip to content

Commit 5587610

Browse files
author
Deyoung Hong
committed
Rearranged codes and added unvme_info.
1 parent 94b022c commit 5587610

File tree

11 files changed

+217
-93
lines changed

11 files changed

+217
-93
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ src/.model
44
src/libunvme.a
55
src/unvmed
66
test/unvme/*_test
7+
test/unvme/unvme_info
78
test/nvme/nvme_identify
89
test/nvme/nvme_get_log_page
910
test/nvme/nvme_get_features

Makefile.def

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030
#
3131

32-
SHELL := /bin/sh
32+
SHELL:=/bin/bash
3333

3434
# Default compilation flags
35-
CFLAGS ?= -O2
36-
CFLAGS += -Wall -fPIC
37-
CPPFLAGS += -D_GNU_SOURCE
35+
CFLAGS?=-O2
36+
CFLAGS+=-Wall -fPIC
37+
CPPFLAGS+=-D_GNU_SOURCE
3838

3939
# To turn on debug message logging
40-
#CPPFLAGS += -DUNVME_DEBUG
40+
#CPPFLAGS+=-DUNVME_DEBUG
4141

4242
# To build the ioengine modules, specify fio directory where the header files
43-
#FIODIR := /opt/fio
43+
#FIODIR:=/opt/fio
4444

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,19 @@ UNVMe requires root privilege to access a device.
6868
Build, Run, and Test
6969
====================
7070

71-
To install the driver and library, run:
71+
To download and install the driver library, run:
7272

73+
$ git clone https://github.com/MicronSSD/unvme.git
7374
$ make install
7475

7576

76-
To set up for UNVMe driver usage (once before running applications), run:
77+
To setup a device for UNVMe usage (do once before running applications), run:
7778

7879
$ unvme-setup bind
7980

8081
By default, all NVMe devices found in the system will be bound to the
8182
VFIO driver enabling them for UNVMe usage. Specific PCI device(s)
82-
may also be specified for binding.
83+
may also be specified for binding, e.g. unvme-setup bind 07:00.0.
8384

8485

8586
To reset device(s) to the NVMe kernel space driver, run:
@@ -112,7 +113,8 @@ To run fio benchmark tests against UNVMe:
112113
1) Download and compile the fio source code (available on https://github.com/axboe/fio).
113114

114115

115-
2) Edit Makefile.def and set FIODIR to the compiled fio source directory.
116+
2) Edit unvme/Makefile.def and set FIODIR to the compiled fio source
117+
directory (or alternatively export the FIODIR variable).
116118

117119

118120
3) Rerun make to include building the fio engine, since setting FIODIR
@@ -189,6 +191,5 @@ As defined in unvme.h, the following functions are supported:
189191

190192
Note that a user space filesystem, namely UNFS, has also been developed
191193
at Micron to work with the UNVMe driver. Such available filesystem enables
192-
major applications like MongoDB to be ported to run on UNVMe driver.
194+
major applications like MongoDB to work with UNVMe driver.
193195
See https://github.com/MicronSSD/unfs.git for details.
194-

src/unvme.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,6 @@ int unvme_free(const unvme_ns_t* ns, void* buf)
111111
return unvme_do_free(ns, buf);
112112
}
113113

114-
/**
115-
* Poll for completion status of a previous IO submission.
116-
* If there's no error, the descriptor will be released.
117-
* @param iod IO descriptor
118-
* @param timeout in seconds
119-
* @return 0 if ok else error status.
120-
*/
121-
int unvme_apoll(unvme_iod_t iod, int timeout)
122-
{
123-
return unvme_do_poll(iod, timeout);
124-
}
125-
126114
/**
127115
* Read data from specified logical blocks on device.
128116
* @param ns namespace handle
@@ -152,6 +140,18 @@ unvme_iod_t unvme_awrite(const unvme_ns_t* ns, int qid,
152140
return unvme_rw(ns, qid, NVME_CMD_WRITE, (void*)buf, slba, nlb);
153141
}
154142

143+
/**
144+
* Poll for completion status of a previous IO submission.
145+
* If there's no error, the descriptor will be released.
146+
* @param iod IO descriptor
147+
* @param timeout in seconds
148+
* @return 0 if ok else error status.
149+
*/
150+
int unvme_apoll(unvme_iod_t iod, int timeout)
151+
{
152+
return unvme_do_poll(iod, timeout);
153+
}
154+
155155
/**
156156
* Read data from specified logical blocks on device.
157157
* @param ns namespace handle
@@ -164,7 +164,10 @@ unvme_iod_t unvme_awrite(const unvme_ns_t* ns, int qid,
164164
int unvme_read(const unvme_ns_t* ns, int qid, void* buf, u64 slba, u32 nlb)
165165
{
166166
unvme_desc_t* desc = unvme_rw(ns, qid, NVME_CMD_READ, buf, slba, nlb);
167-
if (desc) return unvme_do_poll(desc, UNVME_TIMEOUT);
167+
if (desc) {
168+
sched_yield();
169+
return unvme_do_poll(desc, UNVME_TIMEOUT);
170+
}
168171
return -1;
169172
}
170173

@@ -181,7 +184,10 @@ int unvme_write(const unvme_ns_t* ns, int qid,
181184
const void* buf, u64 slba, u32 nlb)
182185
{
183186
unvme_desc_t* desc = unvme_rw(ns, qid, NVME_CMD_WRITE, (void*)buf, slba, nlb);
184-
if (desc) return unvme_do_poll(desc, UNVME_TIMEOUT);
187+
if (desc) {
188+
sched_yield();
189+
return unvme_do_poll(desc, UNVME_TIMEOUT);
190+
}
185191
return -1;
186192
}
187193

src/unvme.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ typedef uint32_t u32; ///< 32-bit unsigned
5151
typedef uint64_t u64; ///< 64-bit unsigned
5252
#endif // _U_TYPE
5353

54-
#define UNVME_TIMEOUT 60 ///< default I/O timeout in seconds
55-
#define UNVME_QSIZE 65 ///< default I/O queue size
54+
#define UNVME_TIMEOUT 30 ///< default I/O timeout in seconds
55+
#define UNVME_QSIZE 256 ///< default I/O queue size
5656

5757
/// Namespace attributes structure
5858
typedef struct _unvme_ns {

src/unvme_core.c

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -70,66 +70,13 @@
7070
/// Log and print an unrecoverable error message and exit
7171
#define FATAL(fmt, arg...) do { ERROR(fmt, ##arg); abort(); } while (0)
7272

73-
/// Fast lock write bit
74-
#define UNVME_LOCKW 0x10000000
75-
7673

7774
// Global static variables
7875
static const char* unvme_log = "/dev/shm/unvme.log"; ///< Log filename
7976
static unvme_session_t* unvme_ses = NULL; ///< session list
8077
static unvme_lock_t unvme_lock = 0; ///< session lock
8178

8279

83-
/**
84-
* Increment read lock and wait if pending write.
85-
* @param lock lock variable
86-
*/
87-
static inline void unvme_lockr(unvme_lock_t* lock)
88-
{
89-
for (;;) {
90-
if (__sync_fetch_and_add(lock, 1) < UNVME_LOCKW) return;
91-
__sync_fetch_and_sub(lock, 1);
92-
sched_yield();
93-
}
94-
}
95-
96-
/**
97-
* Decrement read lock.
98-
* @param lock lock variable
99-
*/
100-
static inline void unvme_unlockr(unvme_lock_t* lock)
101-
{
102-
__sync_fetch_and_sub(lock, 1);
103-
}
104-
105-
/**
106-
* Acquire write lock and wait for all pending read/write.
107-
* @param lock lock variable
108-
*/
109-
static inline void unvme_lockw(unvme_lock_t* lock)
110-
{
111-
for (;;) {
112-
int val = __sync_fetch_and_or(lock, UNVME_LOCKW);
113-
if (val == 0) return;
114-
sched_yield();
115-
116-
// if not pending write then just wait for all reads to clear
117-
if (val < UNVME_LOCKW) {
118-
while (*lock != UNVME_LOCKW) sched_yield();
119-
return;
120-
}
121-
}
122-
}
123-
124-
/**
125-
* Clear the write lock.
126-
* @param lock lock variable
127-
*/
128-
static inline void unvme_unlockw(unvme_lock_t* lock)
129-
{
130-
__sync_fetch_and_and(lock, ~UNVME_LOCKW);
131-
}
132-
13380
/**
13481
* Get a descriptor entry by moving from the free to the use list.
13582
* @param ioq IO queue context
@@ -223,7 +170,7 @@ static int unvme_complete_io(unvme_ioq_t* ioq, int timeout)
223170
if (ioq->cidcount) {
224171
while (ioq->descnext->cidcount == 0) ioq->descnext = ioq->descnext->next;
225172
}
226-
PDEBUG("# c q%d={%d %d %#lx} @%d={%d %#lx} @%d",
173+
PDEBUG("# c q%d={%d %d %#lx} d={%d %d %#lx} @%d",
227174
ioq->nvmeq.id, cid, ioq->cidcount, *ioq->cidmask,
228175
desc->id, desc->cidcount, *desc->cidmask, ioq->descnext->id);
229176
return err;
@@ -326,7 +273,7 @@ static int unvme_submit_io(const unvme_ns_t* ns, unvme_desc_t* desc,
326273
ioq->cidcount++;
327274
desc->cidmask[b] |= mask;
328275
desc->cidcount++;
329-
PDEBUG("# %c %#lx %#x q%d={%d %d %#lx} @%d={%d %#lx}",
276+
PDEBUG("# %c %#lx %#x q%d={%d %d %#lx} d={%d %d %#lx}",
330277
desc->opc == NVME_CMD_READ ? 'r' : 'w', slba, nlb,
331278
ioq->nvmeq.id, cid, ioq->cidcount, *ioq->cidmask,
332279
desc->id, desc->cidcount, *desc->cidmask);
@@ -493,7 +440,7 @@ unvme_ns_t* unvme_do_open(int pci, int nsid, int qcount, int qsize)
493440
while (xses) {
494441
if (xses->ns.pci == pci) {
495442
if (nsid > xses->dev->nscount) {
496-
ERROR("invalid %06x nsid %d", pci, nsid);
443+
ERROR("invalid %06x nsid %d (max %d)", pci, nsid, xses->dev->nscount);
497444
return NULL;
498445
}
499446
if (xses->ns.id == nsid) {
@@ -523,7 +470,7 @@ unvme_ns_t* unvme_do_open(int pci, int nsid, int qcount, int qsize)
523470
nvme_identify_ctlr_t* idc = (nvme_identify_ctlr_t*)dma->buf;
524471
dev->nscount = idc->nn;
525472
if (nsid > dev->nscount) {
526-
ERROR("invalid %06x nsid %d", pci, nsid);
473+
ERROR("invalid %06x nsid %d (max %d)", pci, nsid, dev->nscount);
527474
return NULL;
528475
}
529476

@@ -661,7 +608,7 @@ int unvme_do_free(const unvme_ns_t* ns, void* buf)
661608
*/
662609
int unvme_do_poll(unvme_desc_t* desc, int timeout)
663610
{
664-
PDEBUG("# POLL @%d={%d %#lx}", desc->id, desc->cidcount, *desc->cidmask);
611+
PDEBUG("# POLL d={%d %d %#lx}", desc->id, desc->cidcount, *desc->cidmask);
665612
int err = 0;
666613
while (desc->cidcount) {
667614
if ((err = unvme_complete_io(desc->ioq, timeout)) != 0) break;
@@ -680,7 +627,7 @@ int unvme_do_poll(unvme_desc_t* desc, int timeout)
680627
* @param buf data buffer
681628
* @param slba starting lba
682629
* @param nlb number of logical blocks
683-
* @return 0 if ok else error status.
630+
* @return I/O descriptor or NULL if error.
684631
*/
685632
unvme_desc_t* unvme_rw(const unvme_ns_t* ns, int qid, int opc,
686633
void* buf, u64 slba, u32 nlb)

src/unvme_core.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,10 @@
4242
#include "unvme_log.h"
4343
#include "unvme_vfio.h"
4444
#include "unvme_nvme.h"
45+
#include "unvme_lock.h"
4546
#include "unvme.h"
4647

4748

48-
/// Simple read write lock
49-
typedef int unvme_lock_t;
50-
5149
/// IO memory allocation tracking info
5250
typedef struct _unvme_iomem {
5351
vfio_dma_t** map; ///< dynamic array of allocated memory

src/unvme_lock.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Copyright (c) 2015-2016, Micron Technology, Inc.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* 3. Neither the name of the copyright holder nor the names of its
16+
* contributors may be used to endorse or promote products derived
17+
* from this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
/**
33+
* @file
34+
* @brief UNVMe fast read lock with occasional writes.
35+
*/
36+
37+
#include <sched.h>
38+
39+
/// Lock write bit
40+
#define UNVME_LOCKWBIT 0x80000000
41+
42+
/// Simple read write lock
43+
typedef unsigned unvme_lock_t;
44+
45+
46+
/**
47+
* Increment read lock and wait if pending write.
48+
* @param lock lock variable
49+
*/
50+
static inline void unvme_lockr(unvme_lock_t* lock)
51+
{
52+
for (;;) {
53+
if (!(__sync_fetch_and_add(lock, 1) & UNVME_LOCKWBIT)) return;
54+
__sync_fetch_and_sub(lock, 1);
55+
sched_yield();
56+
}
57+
}
58+
59+
/**
60+
* Decrement read lock.
61+
* @param lock lock variable
62+
*/
63+
static inline void unvme_unlockr(unvme_lock_t* lock)
64+
{
65+
__sync_fetch_and_sub(lock, 1);
66+
}
67+
68+
/**
69+
* Acquire write lock and wait for all pending read/write.
70+
* @param lock lock variable
71+
*/
72+
static inline void unvme_lockw(unvme_lock_t* lock)
73+
{
74+
for (;;) {
75+
int val = __sync_fetch_and_or(lock, UNVME_LOCKWBIT);
76+
if (val == 0) return;
77+
sched_yield();
78+
79+
// if not pending write then just wait for all reads to clear
80+
if (!(val & UNVME_LOCKWBIT)) {
81+
while (*lock != UNVME_LOCKWBIT) sched_yield();
82+
return;
83+
}
84+
}
85+
}
86+
87+
/**
88+
* Clear the write lock.
89+
* @param lock lock variable
90+
*/
91+
static inline void unvme_unlockw(unvme_lock_t* lock)
92+
{
93+
__sync_fetch_and_and(lock, ~UNVME_LOCKWBIT);
94+
}
95+

src/unvme_nvme.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,9 @@ int nvme_cmd_rw(nvme_queue_t* ioq, int opc, u16 cid, int nsid,
466466
cmd->common.prp2 = prp2;
467467
cmd->slba = slba;
468468
cmd->nlb = nlb - 1;
469-
DEBUG_FN("q=%d t=%d cid=%#x nsid=%d lba=%#lx nb=%d (%c)", ioq->id,
470-
ioq->sq_tail, cid, nsid, slba, nlb, opc == NVME_CMD_READ? 'R' : 'W');
469+
DEBUG_FN("q=%d t=%d h=%d cid=%#x nsid=%d lba=%#lx nb=%d (%c)",
470+
ioq->id, ioq->sq_tail, ioq->sq_head, cid, nsid, slba, nlb,
471+
opc == NVME_CMD_READ? 'R' : 'W');
471472
return nvme_submit_cmd(ioq);
472473
}
473474

test/unvme/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
include ../../Makefile.def
3333

3434
TARGETS = unvme_sim_test unvme_api_test unvme_mts_test unvme_lat_test \
35-
unvme_mcd_test
35+
unvme_mcd_test unvme_info
3636

3737
UNVME_SRC = ../../src
3838

0 commit comments

Comments
 (0)