# HG changeset patch # Parent 81db17b31ad4cc95cfaa064e5e916b158312c03b Add parsepath for rumpfs in place of using cn_consume. diff -r 81db17b31ad4 sys/rump/librump/rumpvfs/rumpfs.c --- a/sys/rump/librump/rumpvfs/rumpfs.c Sun Apr 17 01:21:04 2016 -0400 +++ b/sys/rump/librump/rumpvfs/rumpfs.c Sun Apr 17 01:21:41 2016 -0400 @@ -61,6 +61,7 @@ #include #include +static int rump_vop_parsepath(void *); static int rump_vop_lookup(void *); static int rump_vop_getattr(void *); static int rump_vop_setattr(void *); @@ -99,7 +100,7 @@ int (**rump_vnodeop_p)(void *); const struct vnodeopv_entry_desc rump_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, - { &vop_parsepath_desc, genfs_parsepath }, + { &vop_parsepath_desc, rump_vop_parsepath }, { &vop_lookup_desc, rump_vop_lookup }, { &vop_getattr_desc, rump_vop_getattr }, { &vop_setattr_desc, rump_vop_setattr }, @@ -611,6 +612,33 @@ } /* + * parsepath for rump file systems - check for etfs entries. + */ +static int +rump_vop_parsepath(void *v) +{ + struct vop_parsepath_args /* { + struct vnode *a_dvp; + const char *a_name; + size_t *a_retval; + }; */ *ap = v; + struct etfs *et; + bool found; + + /* check for etfs */ + if (ap->a_dvp == rootvnode) { + mutex_enter(&etfs_lock); + found = etfs_find(ap->a_name, &et, false); + mutex_exit(&etfs_lock); + if (found) { + *ap->a_retval = et->et_keylen; + return 0; + } + } + return genfs_parsepath(v); +} + +/* * Simple lookup for rump file systems. * * uhm, this is twisted. C F C C, hope of C C F C looming @@ -631,7 +659,6 @@ struct etfs *et; bool dotdot = (cnp->cn_flags & ISDOTDOT) != 0; int rv = 0; - const char *cp; *vpp = NULL; @@ -664,19 +691,18 @@ mutex_exit(&etfs_lock); if (found) { + if (et->et_keylen != cnp->cn_namelen) { + /* + * This can theoretically happen if an + * etfs entry is added or removed + * while lookups are being done as we + * don't hold etfs_lock across here + * and parsepath. Won't ordinarily be + * the case. No biggie, just retry. + */ + return ERESTART; + } rn = et->et_rn; - cnp->cn_consume += et->et_keylen - cnp->cn_namelen; - /* - * consume trailing slashes if any and clear - * REQUIREDIR if we consumed the full path. - */ - cp = &cnp->cn_nameptr[cnp->cn_namelen]; - cp += cnp->cn_consume; - KASSERT(*cp == '\0' || *cp == '/'); - if (*cp == '\0' && rn->rn_va.va_type != VDIR) - cnp->cn_flags &= ~REQUIREDIR; - while (*cp++ == '/') - cnp->cn_consume++; goto getvnode; } }