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);}