Subject: CROSSMOUNT for null layer
To: None <tech-kern@netbsd.org>
From: Rodolphe De Saint Leger <rdesaintleger@gmail.com>
List: tech-kern
Date: 05/04/2006 22:26:44
Hi,

I'm trying to add a mount flag to layer mount to make them able to
lookup through mount points.

Apparently, it seems to work, but is it ok to do a such thing ?

I added the flag -c (Crossmount) to mount_null, could someone review mycode=
 ?

I there other function to modify (actually, I just modified layer_lookup())=
 ?

Regards,
Rodolphe

here is my test fstab
/usr/roots/sparc        /usr/roots/akima        null rw 0 0
/root   /usr/roots/akima/root   null rw 0 0
/usr/roots/etc/akima    /usr/roots/akima/etc    null rw 0 0
/usr/roots/var/akima    /usr/roots/akima/var    null rw 0 0
/usr/roots/akima        /exports/akima  null rw,-c 0 0

here is my code:
$ diff -r -c ori diffpatch
diff -r -c ori/sbin/mount_null/mount_null.c
diffpatch/sbin/mount_null/mount_null.c
*** ori/sbin/mount_null/mount_null.c    Thu May  4 21:27:18 2006
--- diffpatch/sbin/mount_null/mount_null.c      Thu May  4 21:29:07 2006
***************
*** 49,54 ****
--- 49,55 ----
  #include <sys/param.h>
  #include <sys/mount.h>
  #include <miscfs/nullfs/null.h>
+ #include <miscfs/genfs/layer.h>

  #include <err.h>
  #include <stdio.h>
***************
*** 84,91 ****
        char target[MAXPATHLEN], canon_dir[MAXPATHLEN];

        mntflags =3D 0;
!       while ((ch =3D getopt(argc, argv, "o:")) !=3D -1)
!               switch(ch) {
                case 'o':
                        getmntopts(optarg, mopts, &mntflags, 0);
                        break;
--- 85,99 ----
        char target[MAXPATHLEN], canon_dir[MAXPATHLEN];

        mntflags =3D 0;
!       args.la.mntflags &=3D ~LAYERFS_MFLAGS;
!       while ((ch =3D getopt(argc, argv, "cdo:")) !=3D -1)
!               switch (ch) {
!               case 'c':
!                       args.la.mntflags |=3D LAYERFS_MCROSSMOUNT;
!                       break;
!               case 'd':
!                       args.la.mntflags |=3D LAYERFS_MBYPASSDEBUG;
!                       break;
                case 'o':
                        getmntopts(optarg, mopts, &mntflags, 0);
                        break;
***************
*** 143,148 ****
  usage(void)
  {
        (void)fprintf(stderr,
!               "usage: mount_null [-o options] target_fs mount_point\n");
        exit(1);
  }
--- 151,156 ----
  usage(void)
  {
        (void)fprintf(stderr,
!               "usage: mount_null [-cd] [-o options] target_fs mount_point=
\n");
        exit(1);
  }
diff -r -c ori/sys/miscfs/genfs/layer.h diffpatch/sys/miscfs/genfs/layer.h
*** ori/sys/miscfs/genfs/layer.h        Thu May  4 21:27:58 2006
--- diffpatch/sys/miscfs/genfs/layer.h  Thu May  4 21:29:20 2006
***************
*** 73,81 ****
--- 73,86 ----

  struct layer_args {
        char    *target;                /* Target of loopback  */
+       int     mntflags;               /* Options on the mount */
        struct  export_args     export; /* network export info */
  };

+ #define       LAYERFS_MFLAGS          0x00000fff      /* reserved
layer mount flags  */
+ #define       LAYERFS_MCROSSMOUNT     0x00000002      /* lookup
through mount points */
+ #define       LAYERFS_MBYPASSDEBUG    0x00000001
+
  #ifdef _KERNEL

  struct layer_node;
***************
*** 102,110 ****
        struct simplelock       layerm_hashlock; /* interlock for hash chai=
n. */
  };

- #define       LAYERFS_MFLAGS          0x00000fff      /* reserved
layer mount flags */
- #define       LAYERFS_MBYPASSDEBUG    0x00000001
-
  /*
   * A cache of vnode references
   */
--- 107,112 ----
diff -r -c ori/sys/miscfs/genfs/layer_vnops.c
diffpatch/sys/miscfs/genfs/layer_vnops.c
*** ori/sys/miscfs/genfs/layer_vnops.c  Thu May  4 21:28:13 2006
--- diffpatch/sys/miscfs/genfs/layer_vnops.c    Thu May  4 21:29:35 2006
***************
*** 427,434 ****
        } */ *ap =3D v;
        struct componentname *cnp =3D ap->a_cnp;
        int flags =3D cnp->cn_flags;
!       struct vnode *dvp, *vp, *ldvp;
!       int error, r;

        dvp =3D ap->a_dvp;

--- 427,435 ----
        } */ *ap =3D v;
        struct componentname *cnp =3D ap->a_cnp;
        int flags =3D cnp->cn_flags;
!       struct vnode *dvp, *vp, *ldvp, *cvp;
!       struct mount *cmp;
!       int error, r, mpflags;

        dvp =3D ap->a_dvp;

***************
*** 437,447 ****
--- 438,480 ----
                return (EROFS);

        ldvp =3D LAYERVPTOLOWERVP(dvp);
+
+       mpflags =3D MOUNTTOLAYERMOUNT(dvp->v_mount)->layerm_flags;
+
+       /* Handle ".." lookup */
+       if (((mpflags & LAYERFS_MCROSSMOUNT) !=3D 0) && (cnp->cn_flags &
ISDOTDOT) && ((ldvp->v_flag & VROOT) !=3D 0) && ((dvp->v_flag & VROOT)
=3D=3D 0)) {
+               cvp =3D ldvp->v_mount->mnt_vnodecovered;
+               vput(ldvp);
+               VREF(ldvp =3D cvp);
+               vn_lock(ldvp, LK_EXCLUSIVE | LK_RETRY);
+               cvp =3D NULL;
+       }
+
        ap->a_dvp =3D ldvp;
        error =3D VCALL(ldvp, ap->a_desc->vdesc_offset, ap);
        vp =3D *ap->a_vpp;
        *ap->a_vpp =3D NULL;

+       /* Check for mount point */
+       if (((mpflags & LAYERFS_MCROSSMOUNT) !=3D 0) && (vp !=3D NULL) &&
(vp->v_type =3D=3D VDIR) && ((cmp =3D vp->v_mountedhere) !=3D NULL)) {
+               cvp =3D NULL;
+               /* XXX Taken from vfs_lookup.c */
+               error =3D vfs_busy(cmp, 0, 0);
+
+               if (!error) {
+                       error =3D VFS_ROOT(cmp, &cvp);
+                       vfs_unbusy(cmp);
+
+                       if (error) {
+                               cvp =3D NULL;
+                       }
+               }
+
+               vput(vp);
+               vp =3D cvp;
+               cvp =3D NULL;
+       }
+
        if (error =3D=3D EJUSTRETURN && (flags & ISLASTCN) &&
            (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
            (cnp->cn_nameiop =3D=3D CREATE || cnp->cn_nameiop =3D=3D RENAME=
))
diff -r -c ori/sys/miscfs/nullfs/null_vfsops.c
diffpatch/sys/miscfs/nullfs/null_vfsops.c
*** ori/sys/miscfs/nullfs/null_vfsops.c Thu May  4 21:28:35 2006
--- diffpatch/sys/miscfs/nullfs/null_vfsops.c   Thu May  4 21:29:47 2006
***************
*** 164,169 ****
--- 164,170 ----
        mp->mnt_data =3D nmp;
        mp->mnt_leaf =3D lowerrootvp->v_mount->mnt_leaf;
        nmp->nullm_vfs =3D lowerrootvp->v_mount;
+       nmp->nullm_flags =3D args.la.mntflags & LAYERFS_MFLAGS;
        if (nmp->nullm_vfs->mnt_flag & MNT_LOCAL)
                mp->mnt_flag |=3D MNT_LOCAL;

$

--
int main(void){char*a=3D"\n",b=3D34,*d=3D"int main(void){char*a=3D",
*c=3D"%s%c%cn%c,b=3D34,*d=3D%c%s%c,%s*c=3D%c%s%c,%s*e=3D%c%s%c;%s%s;}%s",
*e=3D"printf(c,d,b,92,b,b,d,b,a,b,c,b,a,b,e,b,a,e,a);exit(0)";
printf(c,d,b,92,b,b,d,b,a,b,c,b,a,b,e,b,a,e,a);exit(0);}