#include "qemu/osdep.h"
#include <dirent.h>
+#include <glib/gstdio.h>
#include "qapi/error.h"
+#include "block/block-io.h"
#include "block/block_int.h"
#include "block/qdict.h"
#include "qemu/module.h"
while((entry=readdir(dir))) {
unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
char* buffer;
- direntry_t* direntry;
struct stat st;
int is_dot=!strcmp(entry->d_name,".");
int is_dotdot=!strcmp(entry->d_name,"..");
/* fill with zeroes up to the end of the cluster */
while(s->directory.next%(0x10*s->sectors_per_cluster)) {
- direntry_t* direntry=array_get_next(&(s->directory));
+ direntry = array_get_next(&(s->directory));
memset(direntry,0,sizeof(direntry_t));
}
#endif
static int enable_write_target(BlockDriverState *bs, Error **errp);
-static int is_consistent(BDRVVVFATState *s);
+static int coroutine_fn is_consistent(BDRVVVFATState *s);
static QemuOptsList runtime_opts = {
.name = "vvfat",
QemuOpts *opts;
int ret;
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
#ifdef DEBUG
vvv = s;
#endif
"The vvfat (rw) format used by node '%s' "
"does not support live migration",
bdrv_get_device_or_node_name(bs));
- ret = migrate_add_blocker(s->migration_blocker, errp);
+ ret = migrate_add_blocker_normal(&s->migration_blocker, errp);
if (ret < 0) {
- error_free(s->migration_blocker);
goto fail;
}
}
}
#endif
-static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
- uint8_t *buf, int nb_sectors)
+static int coroutine_fn GRAPH_RDLOCK
+vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors)
{
BDRVVVFATState *s = bs->opaque;
int i;
if (s->qcow) {
int64_t n;
int ret;
- ret = bdrv_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
- (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
+ ret = bdrv_co_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
+ (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
if (ret < 0) {
return ret;
}
DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
" allocated\n", sector_num,
n >> BDRV_SECTOR_BITS));
- if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
- buf + i * 0x200, 0) < 0) {
+ if (bdrv_co_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
+ buf + i * 0x200, 0) < 0) {
return -1;
}
i += (n >> BDRV_SECTOR_BITS) - 1;
return 0;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vvfat_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
}
}
-static inline bool cluster_was_modified(BDRVVVFATState *s,
- uint32_t cluster_num)
+static inline bool coroutine_fn GRAPH_RDLOCK
+cluster_was_modified(BDRVVVFATState *s, uint32_t cluster_num)
{
int was_modified = 0;
int i;
}
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
- was_modified = bdrv_is_allocated(s->qcow->bs,
- (cluster2sector(s, cluster_num) +
- i) * BDRV_SECTOR_SIZE,
- BDRV_SECTOR_SIZE, NULL);
+ was_modified = bdrv_co_is_allocated(s->qcow->bs,
+ (cluster2sector(s, cluster_num) +
+ i) * BDRV_SECTOR_SIZE,
+ BDRV_SECTOR_SIZE, NULL);
}
/*
* Further, the files/directories handled by this function are
* assumed to be *not* deleted (and *only* those).
*/
-static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
- direntry_t* direntry, const char* path)
+static uint32_t coroutine_fn GRAPH_RDLOCK
+get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const char* path)
{
/*
* This is a little bit tricky:
* This is horribly inefficient, but that is okay, since
* it is rarely executed, if at all.
*/
- int64_t offset = cluster2sector(s, cluster_num);
+ int64_t offs = cluster2sector(s, cluster_num);
vvfat_close_current_file(s);
for (i = 0; i < s->sectors_per_cluster; i++) {
int res;
- res = bdrv_is_allocated(s->qcow->bs,
- (offset + i) * BDRV_SECTOR_SIZE,
- BDRV_SECTOR_SIZE, NULL);
+ res = bdrv_co_is_allocated(s->qcow->bs,
+ (offs + i) * BDRV_SECTOR_SIZE,
+ BDRV_SECTOR_SIZE, NULL);
if (res < 0) {
return -1;
}
if (!res) {
- res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
+ res = vvfat_read(s->bs, offs, s->cluster_buffer, 1);
if (res) {
return -1;
}
- res = bdrv_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
- BDRV_SECTOR_SIZE, s->cluster_buffer,
- 0);
+ res = bdrv_co_pwrite(s->qcow, offs * BDRV_SECTOR_SIZE,
+ BDRV_SECTOR_SIZE, s->cluster_buffer,
+ 0);
if (res < 0) {
return -2;
}
* It returns 0 upon inconsistency or error, and the number of clusters
* used by the directory, its subdirectories and their files.
*/
-static int check_directory_consistency(BDRVVVFATState *s,
- int cluster_num, const char* path)
+static int coroutine_fn GRAPH_RDLOCK
+check_directory_consistency(BDRVVVFATState *s, int cluster_num, const char* path)
{
int ret = 0;
unsigned char* cluster = g_malloc(s->cluster_size);
}
/* returns 1 on success */
-static int is_consistent(BDRVVVFATState* s)
+static int coroutine_fn GRAPH_RDLOCK
+is_consistent(BDRVVVFATState* s)
{
int i, check;
int used_clusters_count = 0;
return 0;
}
-static int commit_direntries(BDRVVVFATState* s,
- int dir_index, int parent_mapping_index)
+static int coroutine_fn GRAPH_RDLOCK
+commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index)
{
direntry_t* direntry = array_get(&(s->directory), dir_index);
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
direntry_t *first_direntry;
- void* direntry = array_get(&(s->directory), current_dir_index);
- int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
+
+ direntry = array_get(&(s->directory), current_dir_index);
+ ret = vvfat_read(s->bs, cluster2sector(s, c), (uint8_t *)direntry,
s->sectors_per_cluster);
if (ret)
return ret;
/* commit one file (adjust contents, adjust mapping),
return first_mapping_index */
-static int commit_one_file(BDRVVVFATState* s,
- int dir_index, uint32_t offset)
+static int coroutine_fn GRAPH_RDLOCK
+commit_one_file(BDRVVVFATState* s, int dir_index, uint32_t offset)
{
direntry_t* direntry = array_get(&(s->directory), dir_index);
uint32_t c = begin_of_direntry(direntry);
direntry_t* direntry = array_get(&(s->directory),
mapping->info.dir.first_dir_index);
uint32_t c = mapping->begin;
- int i = 0;
+ int j = 0;
/* recurse */
while (!fat_eof(s, c)) {
do {
- direntry_t* d = direntry + i;
+ direntry_t *d = direntry + j;
if (is_file(d) || (is_directory(d) && !is_dot(d))) {
int l;
schedule_rename(s, m->begin, new_path);
}
- i++;
- } while((i % (0x10 * s->sectors_per_cluster)) != 0);
+ j++;
+ } while (j % (0x10 * s->sectors_per_cluster) != 0);
c = fat_get(s, c);
}
}
mapping_t* mapping;
int j, parent_path_len;
-#ifdef __MINGW32__
- if (mkdir(commit->path))
- return -5;
-#else
- if (mkdir(commit->path, 0755))
+ if (g_mkdir(commit->path, 0755)) {
return -5;
-#endif
+ }
mapping = insert_mapping(s, commit->param.mkdir.cluster,
commit->param.mkdir.cluster + 1);
/*
* TODO: make sure that the short name is not matching *another* file
*/
-static int handle_commits(BDRVVVFATState* s)
+static int coroutine_fn GRAPH_RDLOCK handle_commits(BDRVVVFATState* s)
{
int i, fail = 0;
fail = -2;
break;
case ACTION_WRITEOUT: {
-#ifndef NDEBUG
- /* these variables are only used by assert() below */
direntry_t* entry = array_get(&(s->directory),
commit->param.writeout.dir_index);
uint32_t begin = begin_of_direntry(entry);
mapping_t* mapping = find_mapping_for_cluster(s, begin);
-#endif
assert(mapping);
assert(mapping->begin == begin);
int begin = commit->param.new_file.first_cluster;
mapping_t* mapping = find_mapping_for_cluster(s, begin);
direntry_t* entry;
- int i;
+ int j;
/* find direntry */
- for (i = 0; i < s->directory.next; i++) {
- entry = array_get(&(s->directory), i);
+ for (j = 0; j < s->directory.next; j++) {
+ entry = array_get(&(s->directory), j);
if (is_file(entry) && begin_of_direntry(entry) == begin)
break;
}
- if (i >= s->directory.next) {
+ if (j >= s->directory.next) {
fail = -6;
continue;
}
mapping->mode = MODE_NORMAL;
mapping->info.file.offset = 0;
- if (commit_one_file(s, i, 0))
+ if (commit_one_file(s, j, 0)) {
fail = -7;
+ }
break;
}
* - recurse direntries from root (using bs->bdrv_pread)
* - delete files corresponding to mappings marked as deleted
*/
-static int do_commit(BDRVVVFATState* s)
+static int coroutine_fn GRAPH_RDLOCK do_commit(BDRVVVFATState* s)
{
int ret = 0;
return 0;
}
-static int try_commit(BDRVVVFATState* s)
+static int coroutine_fn GRAPH_RDLOCK try_commit(BDRVVVFATState* s)
{
vvfat_close_current_file(s);
DLOG(checkpoint());
return do_commit(s);
}
-static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
- const uint8_t *buf, int nb_sectors)
+static int coroutine_fn GRAPH_RDLOCK
+vvfat_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
{
BDRVVVFATState *s = bs->opaque;
int i, ret;
* Use qcow backend. Commit later.
*/
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
- ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
- nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
+ ret = bdrv_co_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
if (ret < 0) {
fprintf(stderr, "Error writing to qcow backend\n");
return ret;
return 0;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vvfat_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
g_free(s->cluster_buffer);
if (s->qcow) {
- migrate_del_blocker(s->migration_blocker);
- error_free(s->migration_blocker);
+ migrate_del_blocker(&s->migration_blocker);
}
}