mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 20:22:46 +00:00
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:
parent
42cabf6965
commit
2592ea8fa4
@ -118,6 +118,9 @@ struct blockif_ctxt {
|
|||||||
TAILQ_HEAD(, blockif_elem) pendq;
|
TAILQ_HEAD(, blockif_elem) pendq;
|
||||||
TAILQ_HEAD(, blockif_elem) busyq;
|
TAILQ_HEAD(, blockif_elem) busyq;
|
||||||
struct blockif_elem reqs[BLOCKIF_MAXREQ];
|
struct blockif_elem reqs[BLOCKIF_MAXREQ];
|
||||||
|
|
||||||
|
/* write cache enable */
|
||||||
|
uint8_t wce;
|
||||||
};
|
};
|
||||||
|
|
||||||
static pthread_once_t blockif_once = PTHREAD_ONCE_INIT;
|
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 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
|
static int
|
||||||
blockif_enqueue(struct blockif_ctxt *bc, struct blockif_req *breq,
|
blockif_enqueue(struct blockif_ctxt *bc, struct blockif_req *breq,
|
||||||
enum blockop op)
|
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);
|
br->offset + bc->sub_file_start_lba);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
err = errno;
|
err = errno;
|
||||||
else
|
else {
|
||||||
br->resid -= len;
|
br->resid -= len;
|
||||||
|
err = blockif_flush_cache(bc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -305,6 +324,8 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf)
|
|||||||
off += len;
|
off += len;
|
||||||
br->resid -= len;
|
br->resid -= len;
|
||||||
}
|
}
|
||||||
|
err = blockif_flush_cache(bc);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case BOP_FLUSH:
|
case BOP_FLUSH:
|
||||||
if (fsync(bc->fd))
|
if (fsync(bc->fd))
|
||||||
@ -464,8 +485,8 @@ blockif_open(const char *optstr, const char *ident)
|
|||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
/* struct diocgattr_arg arg; */
|
/* struct diocgattr_arg arg; */
|
||||||
off_t size, psectsz, psectoff;
|
off_t size, psectsz, psectoff;
|
||||||
int extra, fd, i, sectsz;
|
int fd, i, sectsz;
|
||||||
int nocache, sync, ro, candelete, geom, ssopt, pssopt;
|
int writeback, ro, candelete, geom, ssopt, pssopt;
|
||||||
long sz;
|
long sz;
|
||||||
long long b;
|
long long b;
|
||||||
int err_code = -1;
|
int err_code = -1;
|
||||||
@ -476,11 +497,12 @@ blockif_open(const char *optstr, const char *ident)
|
|||||||
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
ssopt = 0;
|
ssopt = 0;
|
||||||
nocache = 0;
|
|
||||||
sync = 0;
|
|
||||||
ro = 0;
|
ro = 0;
|
||||||
sub_file_assign = 0;
|
sub_file_assign = 0;
|
||||||
|
|
||||||
|
/* writethru is on by default */
|
||||||
|
writeback = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first element in the optstring is always a pathname.
|
* The first element in the optstring is always a pathname.
|
||||||
* Optional elements follow
|
* Optional elements follow
|
||||||
@ -494,10 +516,10 @@ blockif_open(const char *optstr, const char *ident)
|
|||||||
cp = strsep(&xopts, ",");
|
cp = strsep(&xopts, ",");
|
||||||
if (cp == nopt) /* file or device pathname */
|
if (cp == nopt) /* file or device pathname */
|
||||||
continue;
|
continue;
|
||||||
else if (!strcmp(cp, "nocache"))
|
else if (!strcmp(cp, "writeback"))
|
||||||
nocache = 1;
|
writeback = 1;
|
||||||
else if (!strcmp(cp, "sync") || !strcmp(cp, "direct"))
|
else if (!strcmp(cp, "writethru"))
|
||||||
sync = 1;
|
writeback = 0;
|
||||||
else if (!strcmp(cp, "ro"))
|
else if (!strcmp(cp, "ro"))
|
||||||
ro = 1;
|
ro = 1;
|
||||||
else if (sscanf(cp, "sectorsize=%d/%d", &ssopt, &pssopt) == 2)
|
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;
|
* To support "writeback" and "writethru" mode switch during runtime,
|
||||||
sync = 1;
|
* 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;
|
fd = open(nopt, ro ? O_RDONLY : O_RDWR);
|
||||||
if (nocache)
|
|
||||||
extra |= O_DIRECT;
|
|
||||||
if (sync)
|
|
||||||
extra |= O_SYNC;
|
|
||||||
|
|
||||||
fd = open(nopt, (ro ? O_RDONLY : O_RDWR) | extra);
|
|
||||||
if (fd < 0 && !ro) {
|
if (fd < 0 && !ro) {
|
||||||
/* Attempt a r/w fail with a r/o open */
|
/* Attempt a r/w fail with a r/o open */
|
||||||
fd = open(nopt, O_RDONLY | extra);
|
fd = open(nopt, O_RDONLY);
|
||||||
ro = 1;
|
ro = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,6 +667,7 @@ blockif_open(const char *optstr, const char *ident)
|
|||||||
bc->sectsz = sectsz;
|
bc->sectsz = sectsz;
|
||||||
bc->psectsz = psectsz;
|
bc->psectsz = psectsz;
|
||||||
bc->psectoff = psectoff;
|
bc->psectoff = psectoff;
|
||||||
|
bc->wce = writeback;
|
||||||
pthread_mutex_init(&bc->mtx, NULL);
|
pthread_mutex_init(&bc->mtx, NULL);
|
||||||
pthread_cond_init(&bc->cond, NULL);
|
pthread_cond_init(&bc->cond, NULL);
|
||||||
TAILQ_INIT(&bc->freeq);
|
TAILQ_INIT(&bc->freeq);
|
||||||
|
Loading…
Reference in New Issue
Block a user