Module Name: src Committed By: pooka Date: Mon Apr 26 23:40:22 UTC 2010
Modified Files: src/sys/rump/include/rump: rump.h src/sys/rump/librump/rumpvfs: rumpfs.c Log Message: Add directory support to etfs: host directories and their contents will be mapped to rumpfs based on the given key. The directory can be mapped either for a single level or recursively down the entire subtree. To generate a diff of this commit: cvs rdiff -u -r1.40 -r1.41 src/sys/rump/include/rump/rump.h cvs rdiff -u -r1.40 -r1.41 src/sys/rump/librump/rumpvfs/rumpfs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/rump/include/rump/rump.h diff -u src/sys/rump/include/rump/rump.h:1.40 src/sys/rump/include/rump/rump.h:1.41 --- src/sys/rump/include/rump/rump.h:1.40 Sat Apr 24 01:47:34 2010 +++ src/sys/rump/include/rump/rump.h Mon Apr 26 23:40:22 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rump.h,v 1.40 2010/04/24 01:47:34 dholland Exp $ */ +/* $NetBSD: rump.h,v 1.41 2010/04/26 23:40:22 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -76,7 +76,13 @@ #define RUMPCN_FREECRED 0x02 #define RUMPCN_FORCEFREE 0x04 #define RUMP_ETFS_SIZE_ENDOFF ((uint64_t)-1) -enum rump_etfs_type { RUMP_ETFS_REG, RUMP_ETFS_BLK, RUMP_ETFS_CHR }; +enum rump_etfs_type { + RUMP_ETFS_REG, + RUMP_ETFS_BLK, + RUMP_ETFS_CHR, + RUMP_ETFS_DIR, /* only the registered directory */ + RUMP_ETFS_DIR_SUBDIRS /* dir + subdirectories (recursive) */ +}; /* * Something like rump capabilities would be nicer, but let's Index: src/sys/rump/librump/rumpvfs/rumpfs.c diff -u src/sys/rump/librump/rumpvfs/rumpfs.c:1.40 src/sys/rump/librump/rumpvfs/rumpfs.c:1.41 --- src/sys/rump/librump/rumpvfs/rumpfs.c:1.40 Wed Apr 21 07:35:12 2010 +++ src/sys/rump/librump/rumpvfs/rumpfs.c Mon Apr 26 23:40:22 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpfs.c,v 1.40 2010/04/21 07:35:12 pooka Exp $ */ +/* $NetBSD: rumpfs.c,v 1.41 2010/04/26 23:40:22 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.40 2010/04/21 07:35:12 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.41 2010/04/26 23:40:22 pooka Exp $"); #include <sys/param.h> #include <sys/atomic.h> @@ -123,22 +123,29 @@ struct rumpfs_node { struct vattr rn_va; struct vnode *rn_vp; + char *rn_hostpath; + int rn_flags; union { - struct { - char *hostpath; /* VREG */ + struct { /* VREG */ int readfd; int writefd; uint64_t offset; } reg; - LIST_HEAD(, rumpfs_dent) dir; /* VDIR */ + struct { /* VDIR */ + LIST_HEAD(, rumpfs_dent) dents; + int flags; + } dir; } rn_u; }; -#define rn_hostpath rn_u.reg.hostpath #define rn_readfd rn_u.reg.readfd #define rn_writefd rn_u.reg.writefd #define rn_offset rn_u.reg.offset -#define rn_dir rn_u.dir +#define rn_dir rn_u.dir.dents + +#define RUMPNODE_CANRECLAIM 0x01 +#define RUMPNODE_DIR_ET 0x02 +#define RUMPNODE_DIR_ETSUBS 0x04 struct rumpfs_mount { struct vnode *rfsmp_rvp; @@ -157,6 +164,7 @@ struct etfs { char et_key[MAXPATHLEN]; size_t et_keylen; + bool et_prefixkey; LIST_ENTRY(etfs) et_entries; @@ -180,6 +188,12 @@ case RUMP_ETFS_CHR: vt = VCHR; break; + case RUMP_ETFS_DIR: + vt = VDIR; + break; + case RUMP_ETFS_DIR_SUBDIRS: + vt = VDIR; + break; default: panic("invalid et type: %d", et); } @@ -187,32 +201,63 @@ return vt; } +static enum vtype +hft_to_vtype(int hft) +{ + enum vtype vt; + + switch (hft) { + case RUMPUSER_FT_OTHER: + vt = VNON; + break; + case RUMPUSER_FT_DIR: + vt = VDIR; + break; + case RUMPUSER_FT_REG: + vt = VREG; + break; + case RUMPUSER_FT_BLK: + vt = VBLK; + break; + case RUMPUSER_FT_CHR: + vt = VCHR; + break; + default: + vt = VNON; + break; + } + + return vt; +} + static bool -etfs_find(const char *key, struct rumpfs_node **rnp) +etfs_find(const char *key, struct etfs **etp, bool forceprefix) { struct etfs *et; size_t keylen = strlen(key); - bool rv = false; KASSERT(mutex_owned(&etfs_lock)); LIST_FOREACH(et, &etfs_list, et_entries) { - if (keylen == et->et_keylen && strcmp(key, et->et_key) == 0) { - *rnp = et->et_rn; - rv = true; - break; + if ((keylen == et->et_keylen || et->et_prefixkey || forceprefix) + && strncmp(key, et->et_key, et->et_keylen) == 0) { + if (etp) + *etp = et; + return true; } } - return rv; + return false; } +#define REGDIR(ftype) \ + ((ftype) == RUMP_ETFS_DIR || (ftype) == RUMP_ETFS_DIR_SUBDIRS) static int doregister(const char *key, const char *hostpath, enum rump_etfs_type ftype, uint64_t begin, uint64_t size) { struct etfs *et; - struct rumpfs_node *rn_dummy, *rn; + struct rumpfs_node *rn; uint64_t fsize; dev_t rdev = NODEV; devminor_t dmin; @@ -221,13 +266,23 @@ if (rumpuser_getfileinfo(hostpath, &fsize, &hft, &error)) return error; - /* check that we give sensible arguments */ - if (begin > fsize) - return EINVAL; - if (size == RUMP_ETFS_SIZE_ENDOFF) - size = fsize - begin; - if (begin + size > fsize) - return EINVAL; + /* etfs directory requires a directory on the host */ + if (REGDIR(ftype)) { + if (hft != RUMPUSER_FT_DIR) + return ENOTDIR; + if (begin != 0) + return EISDIR; + if (size != RUMP_ETFS_SIZE_ENDOFF) + return EISDIR; + size = fsize; + } else { + if (begin > fsize) + return EINVAL; + if (size == RUMP_ETFS_SIZE_ENDOFF) + size = fsize - begin; + if (begin + size > fsize) + return EINVAL; + } if (ftype == RUMP_ETFS_BLK || ftype == RUMP_ETFS_CHR) { error = rumpblk_register(hostpath, &dmin, begin, size); @@ -241,7 +296,8 @@ strcpy(et->et_key, key); et->et_keylen = strlen(et->et_key); et->et_rn = rn = makeprivate(ettype_to_vtype(ftype), rdev, size); - if (ftype == RUMP_ETFS_REG) { + + if (ftype == RUMP_ETFS_REG || REGDIR(ftype)) { size_t len = strlen(hostpath)+1; rn->rn_hostpath = malloc(len, M_TEMP, M_WAITOK | M_ZERO); @@ -249,8 +305,18 @@ rn->rn_offset = begin; } + if (REGDIR(ftype)) { + rn->rn_flags |= RUMPNODE_DIR_ET; + et->et_prefixkey = true; + } else { + et->et_prefixkey = false; + } + + if (ftype == RUMP_ETFS_DIR_SUBDIRS) + rn->rn_flags |= RUMPNODE_DIR_ETSUBS; + mutex_enter(&etfs_lock); - if (etfs_find(key, &rn_dummy)) { + if (etfs_find(key, NULL, REGDIR(ftype))) { mutex_exit(&etfs_lock); kmem_free(et, sizeof(*et)); /* XXX: rumpblk_deregister(hostpath); */ @@ -261,6 +327,7 @@ return 0; } +#undef REGDIR int rump_etfs_register(const char *key, const char *hostpath, @@ -427,6 +494,7 @@ struct vnode *vp; struct rumpfs_node *rnd = dvp->v_data, *rn; struct rumpfs_dent *rd = NULL; + struct etfs *et; int rv; /* we handle only some "non-special" cases */ @@ -443,20 +511,55 @@ goto out; } - /* check if we are returning a faked block device */ + /* check for etfs */ if (dvp == rootvnode && cnp->cn_nameiop == LOOKUP) { + bool found; mutex_enter(&etfs_lock); - if (etfs_find(cnp->cn_pnbuf, &rn)) { - mutex_exit(&etfs_lock); - cnp->cn_consume = strlen(cnp->cn_nameptr - + cnp->cn_namelen); - cnp->cn_flags &= ~REQUIREDIR; + found = etfs_find(cnp->cn_pnbuf, &et, false); + mutex_exit(&etfs_lock); + + if (found) { + rn = et->et_rn; + cnp->cn_consume += et->et_keylen - cnp->cn_namelen; + if (rn->rn_va.va_type != VDIR) + cnp->cn_flags &= ~REQUIREDIR; goto getvnode; } - mutex_exit(&etfs_lock); } - if (!rd) { + if (rnd->rn_flags & RUMPNODE_DIR_ET) { + uint64_t fsize; + char *newpath; + size_t newpathlen; + int hft, error; + + newpathlen = strlen(rnd->rn_hostpath) + 1 + cnp->cn_namelen + 1; + newpath = malloc(newpathlen, M_TEMP, M_WAITOK); + + strlcpy(newpath, rnd->rn_hostpath, newpathlen); + strlcat(newpath, "/", newpathlen); + strlcat(newpath, cnp->cn_nameptr, newpathlen); + + if (rumpuser_getfileinfo(newpath, &fsize, &hft, &error)) { + free(newpath, M_TEMP); + return error; + } + + /* allow only dirs and regular files */ + if (hft != RUMPUSER_FT_REG && hft != RUMPUSER_FT_DIR) { + free(newpath, M_TEMP); + return ENOENT; + } + + rn = makeprivate(hft_to_vtype(hft), NODEV, fsize); + rn->rn_flags |= RUMPNODE_CANRECLAIM; + if (rnd->rn_flags & RUMPNODE_DIR_ETSUBS) { + rn->rn_flags |= RUMPNODE_DIR_ET | RUMPNODE_DIR_ETSUBS; + } + rn->rn_hostpath = newpath; + + goto getvnode; + } else { LIST_FOREACH(rd, &rnd->rn_dir, rd_entries) { if (strlen(rd->rd_name) == cnp->cn_namelen && strncmp(rd->rd_name, cnp->cn_nameptr, @@ -473,7 +576,6 @@ return EJUSTRETURN; } rn = rd->rd_node; - rd = NULL; getvnode: KASSERT(rn); @@ -756,6 +858,12 @@ mutex_exit(&reclock); vp->v_data = NULL; + if (rn->rn_flags & RUMPNODE_CANRECLAIM) { + if (rn->rn_hostpath) + free(rn->rn_hostpath, M_TEMP); + kmem_free(rn, sizeof(*rn)); + } + return 0; }