qemu-ga: use key-value store to avoid recycling fd handles after restart

Hosts hold on to handles provided by guest-file-open for periods that can
span beyond the life of the qemu-ga process that issued them. Since these
are issued starting from 0 on every restart, we run the risk of issuing
duplicate handles after restarts/reboots.

As a result, users with a stale copy of these handles may end up
reading/writing corrupted data due to their existing handles effectively
being re-assigned to an unexpected file or offset.

We unfortunately do not issue handles as strings, but as integers, so a
solution such as using UUIDs can't be implemented without introducing a
new interface.

As a workaround, we fix this by implementing a persistent key-value store
that will be used to track the value of the last handle that was issued
across restarts/reboots to avoid issuing duplicates.

The store is automatically written to the same directory we currently
set via --statedir to track fsfreeze state, and so should be applicable
for stable releases where this flag is supported.

A follow-up can use this same store for handling fsfreeze state, but
that change is cosmetic and left out for now.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Cc: qemu-stable@nongnu.org

* fixed guest_file_handle_add() return value from uint64_t to int64_t
This commit is contained in:
Michael Roth 2013-03-01 11:40:27 -06:00
parent c5dcb6ae23
commit 39097daf15
3 changed files with 204 additions and 6 deletions

View file

@ -129,14 +129,22 @@ static struct {
QTAILQ_HEAD(, GuestFileHandle) filehandles;
} guest_file_state;
static void guest_file_handle_add(FILE *fh)
static int64_t guest_file_handle_add(FILE *fh, Error **errp)
{
GuestFileHandle *gfh;
int64_t handle;
handle = ga_get_fd_handle(ga_state, errp);
if (error_is_set(errp)) {
return 0;
}
gfh = g_malloc0(sizeof(GuestFileHandle));
gfh->id = fileno(fh);
gfh->id = handle;
gfh->fh = fh;
QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
return handle;
}
static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
@ -158,7 +166,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
{
FILE *fh;
int fd;
int64_t ret = -1;
int64_t ret = -1, handle;
if (!has_mode) {
mode = "r";
@ -184,9 +192,14 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
return -1;
}
guest_file_handle_add(fh);
slog("guest-file-open, handle: %d", fd);
return fd;
handle = guest_file_handle_add(fh, err);
if (error_is_set(err)) {
fclose(fh);
return -1;
}
slog("guest-file-open, handle: %d", handle);
return handle;
}
void qmp_guest_file_close(int64_t handle, Error **err)