Implement rumpblk_deregister, for unregistering fake block devices

(from etfs_deregister).  Prompted by use case from njoly.
This commit is contained in:
pooka 2010-06-15 18:53:48 +00:00
parent eb8e417a7b
commit 28e6724056
3 changed files with 79 additions and 15 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump_vfs_private.h,v 1.12 2010/04/30 21:02:36 pooka Exp $ */
/* $NetBSD: rump_vfs_private.h,v 1.13 2010/06/15 18:53:48 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@ -41,6 +41,7 @@ int rump_devnull_init(void);
#define RUMPBLK_DEVMAJOR 197 /* from conf/majors, XXX: not via config yet */
#define RUMPBLK_SIZENOTSET ((uint64_t)-1)
int rumpblk_register(const char *, devminor_t *, uint64_t, uint64_t);
int rumpblk_deregister(const char *);
int rumpblk_init(void);
void rump_biodone(void *, size_t, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpblk.c,v 1.39 2010/05/01 14:37:53 pooka Exp $ */
/* $NetBSD: rumpblk.c,v 1.40 2010/06/15 18:53:48 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.39 2010/05/01 14:37:53 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.40 2010/06/15 18:53:48 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@ -384,7 +384,6 @@ rumpblk_init(void)
}
}
/* XXX: no deregister */
int
rumpblk_register(const char *path, devminor_t *dmin,
uint64_t offset, uint64_t size)
@ -442,6 +441,39 @@ rumpblk_register(const char *path, devminor_t *dmin,
return 0;
}
/*
* Unregister rumpblk. It's the callers responsibility to make
* sure it's no longer in use.
*/
int
rumpblk_deregister(const char *path)
{
struct rblkdev *rblk;
int i;
mutex_enter(&rumpblk_lock);
for (i = 0; i < RUMPBLK_SIZE; i++) {
if (minors[i].rblk_path&&strcmp(minors[i].rblk_path, path)==0) {
break;
}
}
mutex_exit(&rumpblk_lock);
if (i == RUMPBLK_SIZE)
return ENOENT;
rblk = &minors[i];
KASSERT(rblk->rblk_fd == -1);
KASSERT(rblk->rblk_opencnt == 0);
wincleanup(rblk);
free(rblk->rblk_path, M_TEMP);
rblk->rblk_path = NULL;
memset(&rblk->rblk_label, 0, sizeof(rblk->rblk_label));
return 0;
}
int
rumpblk_open(dev_t dev, int flag, int fmt, struct lwp *l)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpfs.c,v 1.52 2010/06/15 17:23:31 njoly Exp $ */
/* $NetBSD: rumpfs.c,v 1.53 2010/06/15 18:53:48 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.52 2010/06/15 17:23:31 njoly Exp $");
__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.53 2010/06/15 18:53:48 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@ -172,6 +172,8 @@ struct etfs {
char et_key[MAXPATHLEN];
size_t et_keylen;
bool et_prefixkey;
bool et_removing;
devminor_t et_blkmin;
LIST_ENTRY(etfs) et_entries;
@ -267,7 +269,7 @@ doregister(const char *key, const char *hostpath,
struct rumpfs_node *rn;
uint64_t fsize;
dev_t rdev = NODEV;
devminor_t dmin;
devminor_t dmin = -1;
int hft, error;
if (rumpuser_getfileinfo(hostpath, &fsize, &hft, &error))
@ -303,8 +305,10 @@ doregister(const char *key, const char *hostpath,
strcpy(et->et_key, key);
et->et_keylen = strlen(et->et_key);
et->et_rn = rn = makeprivate(ettype_to_vtype(ftype), rdev, size);
et->et_removing = false;
et->et_blkmin = dmin;
if (ftype == RUMP_ETFS_REG || REGDIR(ftype)) {
if (ftype == RUMP_ETFS_REG || REGDIR(ftype) || et->et_blkmin != -1) {
size_t len = strlen(hostpath)+1;
rn->rn_hostpath = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
@ -325,11 +329,12 @@ doregister(const char *key, const char *hostpath,
mutex_enter(&etfs_lock);
if (etfs_find(key, NULL, REGDIR(ftype))) {
mutex_exit(&etfs_lock);
if (et->et_blkmin != -1)
rumpblk_deregister(hostpath);
if (et->et_rn->rn_hostpath != NULL)
free(et->et_rn->rn_hostpath, M_TEMP);
kmem_free(et->et_rn, sizeof(*et->et_rn));
kmem_free(et, sizeof(*et));
/* XXX: rumpblk_deregister(hostpath); */
return EEXIST;
}
LIST_INSERT_HEAD(&etfs_list, et, et_entries);
@ -366,27 +371,53 @@ rump_etfs_register_withsize(const char *key, const char *hostpath,
return doregister(key, hostpath, ftype, begin, size);
}
/* remove etfs mapping. caller's responsibility to make sure it's not in use */
int
rump_etfs_remove(const char *key)
{
struct etfs *et;
size_t keylen = strlen(key);
int rv;
mutex_enter(&etfs_lock);
LIST_FOREACH(et, &etfs_list, et_entries) {
if (keylen == et->et_keylen && strcmp(et->et_key, key) == 0) {
LIST_REMOVE(et, et_entries);
if (et->et_rn->rn_hostpath != NULL)
free(et->et_rn->rn_hostpath, M_TEMP);
kmem_free(et->et_rn, sizeof(*et->et_rn));
kmem_free(et, sizeof(*et));
if (et->et_removing)
et = NULL;
else
et->et_removing = true;
break;
}
}
mutex_exit(&etfs_lock);
if (!et)
return ENOENT;
/*
* ok, we know what we want to remove and have signalled there
* actually are men at work. first, unregister from rumpblk
*/
if (et->et_blkmin != -1) {
rv = rumpblk_deregister(et->et_rn->rn_hostpath);
} else {
rv = 0;
}
KASSERT(rv == 0);
/* then do the actual removal */
mutex_enter(&etfs_lock);
LIST_REMOVE(et, et_entries);
mutex_exit(&etfs_lock);
/* node is unreachable, safe to nuke all device copies */
if (et->et_blkmin != -1)
vdevgone(RUMPBLK_DEVMAJOR, et->et_blkmin, et->et_blkmin, VBLK);
if (et->et_rn->rn_hostpath != NULL)
free(et->et_rn->rn_hostpath, M_TEMP);
kmem_free(et->et_rn, sizeof(*et->et_rn));
kmem_free(et, sizeof(*et));
return 0;
}