diff --git a/tools/libfsimage/common/fsimage.c b/tools/libfsimage/common/fsimage.c
index 5cfa56a84d..1fd302e506 100644
--- a/tools/libfsimage/common/fsimage.c
+++ b/tools/libfsimage/common/fsimage.c
@@ -38,15 +38,32 @@ static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER;
 
 fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options)
 {
-	fsi_t *fsi = NULL;
+	fsi_t *fsi;
 	int fd;
 	int err;
 
 	if ((fd = open(path, O_RDONLY)) == -1)
-		goto fail;
+		return NULL;
+
+	fsi = fsi_fdopen_fsimage(fd, off, options);
+
+	if (fsi)
+		return fsi;
+
+	err = errno;
+	(void) close(fd);
+	errno = err;
+
+	return NULL;
+}
+
+fsi_t *fsi_fdopen_fsimage(int fd, uint64_t off, const char *options)
+{
+	fsi_t *fsi = NULL;
+	int err;
 
 	if ((fsi = malloc(sizeof(*fsi))) == NULL)
-		goto fail;
+		return NULL;
 
 	fsi->f_fd = fd;
 	fsi->f_off = off;
@@ -54,20 +71,17 @@ fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options)
 	fsi->f_bootstring = NULL;
 
 	pthread_mutex_lock(&fsi_lock);
-	err = find_plugin(fsi, path, options);
+	err = find_plugin(fsi, options);
 	pthread_mutex_unlock(&fsi_lock);
-	if (err != 0)
-		goto fail;
 
-	return (fsi);
+	if (!err)
+		return fsi;
 
-fail:
 	err = errno;
-	if (fd != -1)
-		(void) close(fd);
 	free(fsi);
 	errno = err;
-	return (NULL);
+
+	return NULL;
 }
 
 void fsi_close_fsimage(fsi_t *fsi)
@@ -167,3 +181,9 @@ fsi_fs_bootstring(fsi_t *fsi)
 {
 	return (fsi->f_bootstring);
 }
+
+int
+fsi_fd(fsi_t *fsi)
+{
+	return (fsi->f_fd);
+}
diff --git a/tools/libfsimage/common/fsimage_grub.c b/tools/libfsimage/common/fsimage_grub.c
index 258d48bfbb..04397235f7 100644
--- a/tools/libfsimage/common/fsimage_grub.c
+++ b/tools/libfsimage/common/fsimage_grub.c
@@ -221,7 +221,7 @@ fsig_substring(const char *s1, const char *s2)
 }
 
 static int
-fsig_mount(fsi_t *fsi, const char *path, const char *options)
+fsig_mount(fsi_t *fsi, const char *options)
 {
 	fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
 	fsi_file_t *ffi;
diff --git a/tools/libfsimage/common/fsimage_plugin.c b/tools/libfsimage/common/fsimage_plugin.c
index d0cb9e96a6..6645ce3bfe 100644
--- a/tools/libfsimage/common/fsimage_plugin.c
+++ b/tools/libfsimage/common/fsimage_plugin.c
@@ -175,7 +175,7 @@ fail:
 	return (ret);
 }
 
-int find_plugin(fsi_t *fsi, const char *path, const char *options)
+int find_plugin(fsi_t *fsi, const char *options)
 {
 	fsi_plugin_t *fp;
 	int ret = 0;
@@ -185,7 +185,7 @@ int find_plugin(fsi_t *fsi, const char *path, const char *options)
 
 	for (fp = plugins; fp != NULL; fp = fp->fp_next) {
 		fsi->f_plugin = fp;
-		if (fp->fp_ops->fpo_mount(fsi, path, options) == 0)
+		if (fp->fp_ops->fpo_mount(fsi, options) == 0)
 			goto out;
 	}
 
diff --git a/tools/libfsimage/common/fsimage_priv.h b/tools/libfsimage/common/fsimage_priv.h
index 2274403557..779e433b37 100644
--- a/tools/libfsimage/common/fsimage_priv.h
+++ b/tools/libfsimage/common/fsimage_priv.h
@@ -29,6 +29,7 @@ extern C {
 #endif
 
 #include <sys/types.h>
+#include <stdbool.h>
 
 #include "xenfsimage.h"
 #include "xenfsimage_plugin.h"
@@ -54,7 +55,7 @@ struct fsi_file {
 	void *ff_data;
 };
 
-int find_plugin(fsi_t *, const char *, const char *);
+int find_plugin(fsi_t *, const char *);
 
 #ifdef __cplusplus
 };
diff --git a/tools/libfsimage/common/mapfile-GNU b/tools/libfsimage/common/mapfile-GNU
index 2d54d527d7..658f313315 100644
--- a/tools/libfsimage/common/mapfile-GNU
+++ b/tools/libfsimage/common/mapfile-GNU
@@ -3,6 +3,7 @@ VERSION {
 		global:
 			fsi_init;
 			fsi_open_fsimage;
+			fsi_fdopen_fsimage;
 			fsi_close_fsimage;
 			fsi_file_exists;
 			fsi_open_file;
@@ -12,6 +13,7 @@ VERSION {
 			fsi_bootstring_alloc;
 			fsi_bootstring_free;
 			fsi_fs_bootstring;
+			fsi_fd;
 	
 			fsip_fs_set_data;
 			fsip_file_alloc;
diff --git a/tools/libfsimage/common/mapfile-SunOS b/tools/libfsimage/common/mapfile-SunOS
index 48deedb425..a03646ff73 100644
--- a/tools/libfsimage/common/mapfile-SunOS
+++ b/tools/libfsimage/common/mapfile-SunOS
@@ -2,6 +2,7 @@ libfsimage.so.1.0 {
 	global:
 		fsi_init;
 		fsi_open_fsimage;
+		fsi_fdopen_fsimage;
 		fsi_close_fsimage;
 		fsi_file_exists;
 		fsi_open_file;
@@ -11,6 +12,7 @@ libfsimage.so.1.0 {
 		fsi_bootstring_alloc;
 		fsi_bootstring_free;
 		fsi_fs_bootstring;
+		fsi_fd;
 
 		fsip_fs_set_data;
 		fsip_file_alloc;
diff --git a/tools/libfsimage/common/xenfsimage.h b/tools/libfsimage/common/xenfsimage.h
index 341883b2d7..8048cc7470 100644
--- a/tools/libfsimage/common/xenfsimage.h
+++ b/tools/libfsimage/common/xenfsimage.h
@@ -44,6 +44,7 @@ typedef struct fsi_file fsi_file_t;
 int fsi_init(void);
 
 fsi_t *fsi_open_fsimage(const char *, uint64_t, const char *);
+fsi_t *fsi_fdopen_fsimage(int, uint64_t, const char *);
 void fsi_close_fsimage(fsi_t *);
 
 int fsi_file_exists(fsi_t *, const char *);
@@ -57,6 +58,8 @@ char *fsi_bootstring_alloc(fsi_t *, size_t);
 void fsi_bootstring_free(fsi_t *);
 char *fsi_fs_bootstring(fsi_t *);
 
+int fsi_fd(fsi_t *);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/tools/libfsimage/common/xenfsimage_plugin.h b/tools/libfsimage/common/xenfsimage_plugin.h
index 4135769018..996ea5ecbb 100644
--- a/tools/libfsimage/common/xenfsimage_plugin.h
+++ b/tools/libfsimage/common/xenfsimage_plugin.h
@@ -38,7 +38,7 @@ typedef struct fsi_plugin fsi_plugin_t;
 
 typedef struct fsi_plugin_ops {
 	int fpo_version;
-	int (*fpo_mount)(fsi_t *, const char *, const char *);
+	int (*fpo_mount)(fsi_t *, const char *);
 	int (*fpo_umount)(fsi_t *);
 	fsi_file_t *(*fpo_open)(fsi_t *, const char *);
 	ssize_t (*fpo_read)(fsi_file_t *, void *, size_t);
diff --git a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
index 864a15b349..9f07ea288f 100644
--- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
+++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
@@ -25,15 +25,25 @@
 #include INCLUDE_EXTFS_H
 #include <errno.h>
 #include <inttypes.h>
+#include <stdio.h>
 
 static int
-ext2lib_mount(fsi_t *fsi, const char *name, const char *options)
+ext2lib_mount(fsi_t *fsi, const char *options)
 {
 	int err;
 	char opts[30] = "";
 	ext2_filsys *fs;
 	uint64_t offset = fsip_fs_offset(fsi);
 
+	/*
+	 * We must choose unixfd_io_manager rather than unix_io_manager in
+	 * order for the library to accept fd strings instead of paths. It
+	 * still means we must pass a string representing an fd rather than
+	 * an int, but at least this way we don't need to pass paths around
+	 */
+	char name[32] = {0};
+	(void)snprintf(name, sizeof(name) - 1, "%d", fsi_fd(fsi));
+
 	if (offset)
 		snprintf(opts, 29, "offset=%" PRId64, offset);
 
@@ -41,7 +51,7 @@ ext2lib_mount(fsi_t *fsi, const char *name, const char *options)
 	if (fs == NULL)
 		return (-1);
 
-	err = ext2fs_open2(name, opts, 0, 0, 0, unix_io_manager, fs);
+	err = ext2fs_open2(name, opts, 0, 0, 0, unixfd_io_manager, fs);
 
 	if (err != 0) {
 		free(fs);
