# HG changeset patch # Parent 7b65eceff7c2d94d82dfb89f4f4e21e36f0edb0b Onionfs needs to know about parsepath too, in case it has one of the other cases underneath it. The solution here is not really very good (take the longer path-to-consume if they're different) but it will serve for the cases that exist. (If we were to add a fs that really uses different naming semantics, we'd have to take additional steps; probably it doesn't make sense to allow unionfs to union such a thing with a normal fs and attempting it should fail at mount time.) Update fs/unionfs as well to avoid increasing the current set of compile failures there. Though maybe it's time to just remove fs/unionfs. diff -r 7b65eceff7c2 sys/fs/union/union_vnops.c --- a/sys/fs/union/union_vnops.c Sun Apr 17 01:21:41 2016 -0400 +++ b/sys/fs/union/union_vnops.c Sun Apr 17 01:23:31 2016 -0400 @@ -93,6 +93,7 @@ #include #include +int union_parsepath(void *); int union_lookup(void *); int union_create(void *); int union_whiteout(void *); @@ -144,7 +145,7 @@ int (**union_vnodeop_p)(void *); const struct vnodeopv_entry_desc union_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, - { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ + { &vop_parsepath_desc, union_parsepath }, /* parsepath */ { &vop_lookup_desc, union_lookup }, /* lookup */ { &vop_create_desc, union_create }, /* create */ { &vop_whiteout_desc, union_whiteout }, /* whiteout */ @@ -196,6 +197,40 @@ ((vp)->v_type == VBLK || (vp)->v_type == VCHR || \ (vp)->v_type == VSOCK || (vp)->v_type == VFIFO) +int +union_parsepath(void *v) +{ + struct vop_parsepath_args /* { + struct vnode *a_dvp; + const char *a_name; + size_t *a_retval; + } */ *ap = v; + struct vnode *upperdvp, *lowerdvp; + size_t upper, lower; + int error; + + upperdvp = UPPERVP(ap->a_dvp); + lowerdvp = LOWERVP(ap->a_dvp); + + error = VOP_PARSEPATH(upperdvp, ap->a_name, &upper); + if (error) { + return error; + } + + error = VOP_PARSEPATH(lowerdvp, ap->a_name, &lower); + if (error) { + return error; + } + + /* + * If they're different, use the larger one. This is not a + * comprehensive solution, but it's sufficient for the + * non-default cases of parsepath that currently exist. + */ + *ap->a_retval = MAX(upper, lower); + return 0; +} + static int union_lookup1(struct vnode *udvp, struct vnode **dvpp, struct vnode **vpp, struct componentname *cnp) diff -r 7b65eceff7c2 sys/fs/unionfs/unionfs_vnops.c --- a/sys/fs/unionfs/unionfs_vnops.c Sun Apr 17 01:21:41 2016 -0400 +++ b/sys/fs/unionfs/unionfs_vnops.c Sun Apr 17 01:23:31 2016 -0400 @@ -65,6 +65,42 @@ #endif static int +unionfs_parsepath(void *v) +{ + struct vop_parsepath_args /* { + struct vnode *a_dvp; + const char *a_name; + size_t *a_retval; + } */ *ap = v; + struct unionfs_node *dunp; + struct vnode *upperdvp, *lowerdvp; + size_t upper, lower; + int error; + + dunp = VTOUNIONFS(ap->a_dvp); + upperdvp = dunp->un_uppervp; + lowerdvp = dunp->un_lowervp; + + error = VOP_PARSEPATH(upperdvp, ap->a_name, &upper); + if (error) { + return error; + } + + error = VOP_PARSEPATH(lowerdvp, ap->a_name, &lower); + if (error) { + return error; + } + + /* + * If they're different, use the larger one. This is not a + * comprehensive solution, but it's sufficient for the + * non-default cases of parsepath that currently exist. + */ + *ap->a_retval = MAX(upper, lower); + return 0; +} + +static int unionfs_lookup(void *v) { struct vop_lookup_args *ap = v; @@ -1809,7 +1845,7 @@ int (**unionfs_vnodeop_p)(void *); const struct vnodeopv_entry_desc unionfs_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, - { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ + { &vop_parsepath_desc, unionfs_parsepath }, /* parsepath */ { &vop_lookup_desc, unionfs_lookup }, /* lookup */ { &vop_create_desc, unionfs_create }, /* create */ { &vop_whiteout_desc, unionfs_whiteout }, /* whiteout */