dm: storage: support writethru and writeback mode

In writethru mode, guest storage write are reported completed only
when the data has been written to physical storage.

In writeback mode, guest storage write are reported completed when
data is placed in SOS page cache. Needs to be flushed to the
physical storage.

USAGE:
    -s x,virtio-blk,<filepath>,writeback
    -s x,virtio-blk,<filepath>,writethru

The default mode is *writethru*

Signed-off-by: Conghui Chen <conghui.chen@intel.com>
Reviewed-by: Shuo Liu <shuo.a.liu@intel.com>
Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
Conghui Chen 2018-07-26 09:01:22 +08:00 committed by lijinxia
parent 42cabf6965
commit 2592ea8fa4

View File

@ -118,6 +118,9 @@ struct blockif_ctxt {
TAILQ_HEAD(, blockif_elem) pendq;
TAILQ_HEAD(, blockif_elem) busyq;
struct blockif_elem reqs[BLOCKIF_MAXREQ];
/* write cache enable */
uint8_t wce;
};
static pthread_once_t blockif_once = PTHREAD_ONCE_INIT;
@ -131,6 +134,20 @@ struct blockif_sig_elem {
static struct blockif_sig_elem *blockif_bse_head;
static int
blockif_flush_cache(struct blockif_ctxt *bc)
{
int err;
err = 0;
assert(bc != NULL);
if (!bc->wce) {
if (fsync(bc->fd))
err = errno;
}
return err;
}
static int
blockif_enqueue(struct blockif_ctxt *bc, struct blockif_req *breq,
enum blockop op)
@ -275,8 +292,10 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf)
br->offset + bc->sub_file_start_lba);
if (len < 0)
err = errno;
else
else {
br->resid -= len;
err = blockif_flush_cache(bc);
}
break;
}
i = 0;
@ -305,6 +324,8 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf)
off += len;
br->resid -= len;
}
err = blockif_flush_cache(bc);
break;
case BOP_FLUSH:
if (fsync(bc->fd))
@ -464,8 +485,8 @@ blockif_open(const char *optstr, const char *ident)
struct stat sbuf;
/* struct diocgattr_arg arg; */
off_t size, psectsz, psectoff;
int extra, fd, i, sectsz;
int nocache, sync, ro, candelete, geom, ssopt, pssopt;
int fd, i, sectsz;
int writeback, ro, candelete, geom, ssopt, pssopt;
long sz;
long long b;
int err_code = -1;
@ -476,11 +497,12 @@ blockif_open(const char *optstr, const char *ident)
fd = -1;
ssopt = 0;
nocache = 0;
sync = 0;
ro = 0;
sub_file_assign = 0;
/* writethru is on by default */
writeback = 0;
/*
* The first element in the optstring is always a pathname.
* Optional elements follow
@ -494,10 +516,10 @@ blockif_open(const char *optstr, const char *ident)
cp = strsep(&xopts, ",");
if (cp == nopt) /* file or device pathname */
continue;
else if (!strcmp(cp, "nocache"))
nocache = 1;
else if (!strcmp(cp, "sync") || !strcmp(cp, "direct"))
sync = 1;
else if (!strcmp(cp, "writeback"))
writeback = 1;
else if (!strcmp(cp, "writethru"))
writeback = 0;
else if (!strcmp(cp, "ro"))
ro = 1;
else if (sscanf(cp, "sectorsize=%d/%d", &ssopt, &pssopt) == 2)
@ -513,20 +535,17 @@ blockif_open(const char *optstr, const char *ident)
}
}
/* enforce a write-through policy by default */
nocache = 1;
sync = 1;
/*
* To support "writeback" and "writethru" mode switch during runtime,
* O_SYNC is not used directly, as O_SYNC flag cannot dynamic change
* after file is opened. Instead, we call fsync() after each write
* operation to emulate it.
*/
extra = 0;
if (nocache)
extra |= O_DIRECT;
if (sync)
extra |= O_SYNC;
fd = open(nopt, (ro ? O_RDONLY : O_RDWR) | extra);
fd = open(nopt, ro ? O_RDONLY : O_RDWR);
if (fd < 0 && !ro) {
/* Attempt a r/w fail with a r/o open */
fd = open(nopt, O_RDONLY | extra);
fd = open(nopt, O_RDONLY);
ro = 1;
}
@ -648,6 +667,7 @@ blockif_open(const char *optstr, const char *ident)
bc->sectsz = sectsz;
bc->psectsz = psectsz;
bc->psectoff = psectoff;
bc->wce = writeback;
pthread_mutex_init(&bc->mtx, NULL);
pthread_cond_init(&bc->cond, NULL);
TAILQ_INIT(&bc->freeq);