FreeBSD Bugzilla – Attachment 14505 Details for
Bug 27250
[unionfs] [patch] unionfs filesystem panics in large number of situations
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 14.22 KB, created by
vova
on 2001-05-10 18:10:01 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
vova
Created:
2001-05-10 18:10:01 UTC
Size:
14.22 KB
patch
obsolete
>Index: src/sys/kern/vfs_syscalls.c >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/kern/vfs_syscalls.c,v >retrieving revision 1.151.2.5.2.3 >diff -u -r1.151.2.5.2.3 vfs_syscalls.c >--- src/sys/kern/vfs_syscalls.c 2001/02/27 13:25:48 1.151.2.5.2.3 >+++ src/sys/kern/vfs_syscalls.c 2001/05/04 07:35:07 >@@ -81,7 +81,9 @@ > const struct timespec *, int)); > static int usermount = 0; /* if 1, non-root can mount fs. */ > >+/* > int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *)); >+*/ > > SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); > >@@ -2854,7 +2859,7 @@ > if ((fp->f_flag & FREAD) == 0) > return (EBADF); > vp = (struct vnode *)fp->f_data; >-unionread: >+/*unionread:*/ > if (vp->v_type != VDIR) > return (EINVAL); > aiov.iov_base = SCARG(uap, buf); >@@ -2921,6 +2926,7 @@ > VOP_UNLOCK(vp, 0, p); > if (error) > return (error); >+/* > if (SCARG(uap, count) == auio.uio_resid) { > if (union_dircheckp) { > error = union_dircheckp(p, &vp, fp); >@@ -2940,6 +2946,7 @@ > goto unionread; > } > } >+*/ > error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), > sizeof(long)); > p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; >@@ -2980,7 +2987,7 @@ > if ((fp->f_flag & FREAD) == 0) > return (EBADF); > vp = (struct vnode *)fp->f_data; >-unionread: >+/*unionread:*/ > if (vp->v_type != VDIR) > return (EINVAL); > aiov.iov_base = SCARG(uap, buf); >@@ -2999,6 +3006,7 @@ > VOP_UNLOCK(vp, 0, p); > if (error) > return (error); >+/* > if (SCARG(uap, count) == auio.uio_resid) { > if (union_dircheckp) { > error = union_dircheckp(p, &vp, fp); >@@ -3018,6 +3026,7 @@ > goto unionread; > } > } >+*/ > if (SCARG(uap, basep) != NULL) { > error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), > sizeof(long)); >Index: src/sys/vm/vm_mmap.c >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/vm/vm_mmap.c,v >retrieving revision 1.108.2.2.2.1 >diff -u -r1.108.2.2.2.1 vm_mmap.c >--- src/sys/vm/vm_mmap.c 2000/11/03 00:37:39 1.108.2.2.2.1 >+++ src/sys/vm/vm_mmap.c 2001/05/04 07:35:07 >@@ -78,6 +78,8 @@ > #include <vm/vm_page.h> > #include <vm/vm_kern.h> > >+#include <miscfs/union/union.h> >+ > #ifndef _SYS_SYSPROTO_H_ > struct sbrk_args { > int incr; >@@ -1074,6 +1076,15 @@ > /* > * Lookup/allocate object. > */ >+ vp = (struct vnode *) handle; >+#if 1 >+ if( vp ) { >+ while( vp->v_tag == VT_UNION) { >+ vp = OTHERVP(vp); >+ } >+ handle = (void *)vp; >+ } >+#endif > if (flags & MAP_ANON) { > type = OBJT_DEFAULT; > /* >@@ -1082,7 +1093,7 @@ > if (handle == 0) > foff = 0; > } else { >- vp = (struct vnode *) handle; >+/* vp = (struct vnode *) handle; */ > if (vp->v_type == VCHR) { > type = OBJT_DEVICE; > handle = (void *)(intptr_t)vp->v_rdev; >Index: src/sys/miscfs/union/union.h >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/miscfs/union/union.h,v >retrieving revision 1.17 >diff -u -r1.17 union.h >--- src/sys/miscfs/union/union.h 1999/12/29 04:54:48 1.17 >+++ src/sys/miscfs/union/union.h 2001/05/04 07:35:07 >@@ -97,6 +103,9 @@ > #endif > }; > >+#define DOCACHE 1 /*union_allocvp argument: default "1"*/ >+ >+#define UPPERLOCK 0 /* Need uppervp to lock */ > /* > * XXX UN_ULOCK - indicates that the uppervp is locked > * >Index: src/sys/miscfs/union/union_subr.c >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/miscfs/union/union_subr.c,v >retrieving revision 1.43 >diff -u -r1.43 union_subr.c >--- src/sys/miscfs/union/union_subr.c 1999/12/15 23:02:12 1.43 >+++ src/sys/miscfs/union/union_subr.c 2001/05/04 07:35:07 >@@ -343,7 +344,9 @@ > { > int error; > struct union_node *un = 0; >+/* > struct vnode *xlowervp = NULLVP; >+*/ > struct union_mount *um = MOUNTTOUNIONMOUNT(mp); > struct proc *p = (cnp) ? cnp->cn_proc : curproc; > int hash = 0; >@@ -354,7 +357,10 @@ > panic("union: unidentifiable allocation"); > > if (uppervp && lowervp && (uppervp->v_type != lowervp->v_type)) { >+/* > xlowervp = lowervp; >+*/ >+ vrele(lowervp); > lowervp = NULLVP; > } > >@@ -597,8 +603,10 @@ > } > > out: >+/* > if (xlowervp) > vrele(xlowervp); >+*/ > > if (docache) > union_list_unlock(hash); >@@ -1304,6 +1324,7 @@ > /* > * Module glue to remove #ifdef UNION from vfs_syscalls.c > */ >+#ifdef NEED_BAD_HACK > static int > union_dircheck(struct proc *p, struct vnode **vp, struct file *fp) > { >@@ -1312,6 +1333,9 @@ > if ((*vp)->v_op == union_vnodeop_p) { > struct vnode *lvp; > >+ if(LOWERVP(*vp) == NULL) { >+ return 0; >+ } > lvp = union_dircache(*vp, p); > if (lvp != NULLVP) { > struct vattr va; >@@ -1347,13 +1371,15 @@ > } > return error; > } >+#endif > >+#ifdef NEED_BAD_HACK > static int > union_modevent(module_t mod, int type, void *data) > { > switch (type) { > case MOD_LOAD: >- union_dircheckp = union_dircheck; >+ union_dircheckp = union_dircheck; > break; > case MOD_UNLOAD: > union_dircheckp = NULL; >@@ -1371,3 +1397,4 @@ > }; > > DECLARE_MODULE(union_dircheck, union_mod, SI_SUB_VFS, SI_ORDER_ANY); >+#endif >Index: src/sys/miscfs/union/union_vfsops.c >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/miscfs/union/union_vfsops.c,v >retrieving revision 1.39 >diff -u -r1.39 union_vfsops.c >--- src/sys/miscfs/union/union_vfsops.c 1999/12/19 06:07:52 1.39 >+++ src/sys/miscfs/union/union_vfsops.c 2001/05/04 07:35:07 >@@ -407,7 +412,7 @@ > VREF(um->um_lowervp); > > error = union_allocvp(vpp, mp, NULLVP, NULLVP, NULL, >- um->um_uppervp, um->um_lowervp, 1); >+ um->um_uppervp, um->um_lowervp, DOCACHE); > UDEBUG(("error %d\n", error)); > UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp, > VOP_ISLOCKED(um->um_uppervp, NULL))); >@@ -415,6 +420,22 @@ > return (error); > } > >+static void union_statfs_copy( struct statfs *sbp, struct statfs *mstat, struct statfs *main ) { >+ sbp->f_bsize = mstat->f_bsize; >+ sbp->f_blocks = mstat->f_blocks; >+ sbp->f_bfree = mstat->f_bfree; >+ sbp->f_bavail = mstat->f_bavail; >+ sbp->f_files = mstat->f_files; >+ sbp->f_ffree = mstat->f_ffree; >+ sbp->f_flags = mstat->f_flags; >+ sbp->f_iosize = mstat->f_iosize; >+ if (sbp != main) { >+ sbp->f_type = main->f_type; >+ bcopy(&main->f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); >+ bcopy(&main->f_mntonname, sbp->f_mntonname, MNAMELEN); >+ bcopy(&main->f_mntfromname, sbp->f_mntfromname, MNAMELEN); >+ } >+} > static int > union_statfs(mp, sbp, p) > struct mount *mp; >@@ -432,9 +453,22 @@ > bzero(&mstat, sizeof(mstat)); > > if (um->um_lowervp) { >+ if( um->um_lowervp->v_mount == um->um_uppervp->v_mount ) { >+ error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p); >+ union_statfs_copy(sbp, &mstat, &mp->mnt_stat); >+ return error; >+ } > error = VFS_STATFS(um->um_lowervp->v_mount, &mstat, p); >- if (error) >- return (error); >+/*uprintf("Lowrvp fsstat return %d\n", error);*/ >+ if (error) { >+ error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p); >+ union_statfs_copy(sbp, &mstat, &mp->mnt_stat); >+ return error; >+ } >+ } else { >+ error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p); >+ union_statfs_copy(sbp, &mstat, &mp->mnt_stat); >+ return error; > } > > /* now copy across the "interesting" information and fake the rest */ >@@ -452,6 +486,7 @@ > sbp->f_ffree = mstat.f_ffree; > > error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p); >+/*uprintf("Uppervp fsstat return %d\n", error); */ > if (error) > return (error); > >Index: src/sys/miscfs/union/union_vnops.c >=================================================================== >RCS file: /home1/cvsroot//freebsd/src/sys/miscfs/union/union_vnops.c,v >retrieving revision 1.72 >diff -u -r1.72 union_vnops.c >--- src/sys/miscfs/union/union_vnops.c 1999/12/15 23:02:14 1.72 >+++ src/sys/miscfs/union/union_vnops.c 2001/05/04 07:35:07 >@@ -275,6 +275,8 @@ > return (0); > } > >+#define NOOPEN_LOWER 0 >+ > static int > union_lookup(ap) > struct vop_lookup_args /* { >@@ -300,6 +302,9 @@ > > *ap->a_vpp = NULLVP; > >+/*if ((cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { >+printf("lookup: [%.*s] for %d\ncnp->cn_consume = %d\n",cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_nameiop,cnp->cn_consume); >+}*/ > /* > * Disallow write attemps to the filesystem mounted read-only. > */ >@@ -367,7 +372,12 @@ > (uppervp ? uppervp->v_usecount : -99), > (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99) > )); >- >+/* >+ if(uerror == EACCES) { >+ error = uerror; >+ goto out; >+ } >+*/ > /* > * Disallow write attemps to the filesystem mounted read-only. > */ >@@ -538,9 +548,52 @@ > VOP_UNLOCK(lowervp, 0, p); > if (upperdvp) > VOP_UNLOCK(upperdvp, 0, p); >- >- error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, >- uppervp, lowervp, 1); >+/* >+printf("lookup_end: [%.*s] for %d\n",cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_nameiop); >+*/ >+ { >+ struct vnode *tmp; >+ tmp = (uppervp != NULL) ? uppervp : lowervp; >+/* >+printf("vnode = %p\ncnp->cn_nameiop = %d, cnp->cn_name = %.*s, type = %d\nv_usecount = %d\n", >+ tmp, >+ cnp->cn_nameiop, cnp->cn_namelen, cnp->cn_nameptr, tmp->v_type, >+ tmp->v_usecount); >+*/ >+ if( (cnp->cn_nameiop == LOOKUP && >+ ( >+#if NOOPEN_LOWER >+ tmp->v_type != VREG && >+#endif >+ tmp->v_type != VDIR && >+ tmp->v_type != VLNK) >+ ) >+#if NOOPEN_LOWER >+ || >+ (tmp->v_type == VREG && (uppervp != NULL) && ( >+ cnp->cn_nameiop == LOOKUP || cnp->cn_nameiop == CREATE)) >+#endif >+ ){ >+ *(ap->a_vpp) = tmp; >+ if(uppervp && lowervp) { >+ vput(lowervp); >+ lowervp = 0; >+ } >+ if (upperdvp) { >+ if (upperdvp == tmp) { >+ vrele(upperdvp); >+ } else { >+ vput(upperdvp); >+ } >+ upperdvp = NULL; >+ } >+ error = 0; >+ }else{ >+ error = union_allocvp(ap->a_vpp, dvp->v_mount, >+ dvp, upperdvp, cnp, >+ uppervp, lowervp, 1); >+ } >+ } > > UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? ((*ap->a_vpp)->v_usecount) : -99)); > >@@ -612,7 +665,8 @@ > if (cnp->cn_namelen == 1 && > cnp->cn_nameptr[0] == '.' && > *ap->a_vpp != dvp) { >- panic("union_lookup returning . (%p) not same as startdir (%p)", ap->a_vpp, dvp); >+ /*panic("union_lookup returning . (%p) not same as startdir (%p)", *ap->a_vpp, dvp);*/ >+ printf("union_lookup returning . (%p) not same as startdir (%p). error = %d\n", *ap->a_vpp, dvp, error); > } > #endif > >@@ -642,6 +696,9 @@ > int error = EROFS; > > if ((dvp = union_lock_upper(dun, p)) != NULL) { >+#if 1 >+ error = VOP_CREATE(dvp, ap->a_vpp, cnp, ap->a_vap); >+#else > struct vnode *vp; > struct mount *mp; > >@@ -654,6 +711,7 @@ > cnp, vp, NULLVP, 1); > UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount)); > } >+#endif > union_unlock_upper(dvp, p); > } > return (error); >@@ -672,6 +730,10 @@ > struct vnode *uppervp; > int error = EOPNOTSUPP; > >+ if (cnp == NULL) { >+ return 0; >+ } >+ > if ((uppervp = union_lock_upper(un, cnp->cn_proc)) != NULLVP) { > error = VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags); > union_unlock_upper(uppervp, cnp->cn_proc); >@@ -1101,8 +1163,10 @@ > struct vnode *uppervp; > int error; > >- if ((uppervp = union_lock_upper(un, p)) == NULLVP) >+ if ((uppervp = union_lock_upper(un, p)) == NULLVP) { >+ printf("un_uppervp: %x\n", un->un_uppervp); > panic("union: missing upper layer in write"); >+ } > > /* > * Since our VM pages are associated with our vnode rather then >@@ -1318,7 +1382,7 @@ > > if (tun->un_uppervp == NULLVP) { > vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); >-#if 0 >+#if UPPERLOCK > if (dun->un_uppervp == tun->un_dirvp) { > if (dun->un_flags & UN_ULOCK) { > dun->un_flags &= ~UN_ULOCK; >@@ -1327,7 +1391,7 @@ > } > #endif > error = union_copyup(tun, 1, cnp->cn_cred, p); >-#if 0 >+#if UPPERLOCK > if (dun->un_uppervp == tun->un_dirvp) { > vn_lock(dun->un_uppervp, > LK_EXCLUSIVE | LK_RETRY, p); >@@ -1647,12 +1711,35 @@ > struct proc *p = ap->a_uio->uio_procp; > struct vnode *uvp; > int error = 0; >+ int save_resid; > >- if ((uvp = union_lock_upper(un, p)) != NULLVP) { >+ if ((un->un_uppersz == VNOVAL || un->un_uppersz >= ap->a_uio->uio_offset) && (uvp = union_lock_upper(un, p)) != NULLVP) { >+/*uprintf("readdir un->un_uppersz = %d ap->a_uio->uio_offset = %d\n", un->un_uppersz, ap->a_uio->uio_offset);*/ > ap->a_vp = uvp; >+ save_resid = ap->a_uio->uio_resid; > error = VCALL(uvp, VOFFSET(vop_readdir), ap); >+ if(error) { >+ return(error); >+ } > union_unlock_upper(uvp, p); >+ if(un->un_uppersz == VNOVAL || ap->a_uio->uio_offset > un->un_uppersz) { >+ un->un_uppersz = ap->a_uio->uio_offset; >+ } >+ if(ap->a_uio->uio_resid == save_resid) { >+ un->un_uppersz = ap->a_uio->uio_offset; >+ } else { >+ return(0); >+ } > } >+ if ((uvp = un->un_lowervp)) { >+ ap->a_uio->uio_offset -= un->un_uppersz; >+ ap->a_vp = uvp; >+ VREF(uvp); >+ vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, p); >+ error = VCALL(uvp, VOFFSET(vop_readdir), ap); >+ vput(uvp); >+ ap->a_uio->uio_offset += un->un_uppersz; >+ } > return(error); > } > >@@ -1718,7 +1805,7 @@ > un->un_dircache = 0; > } > >-#if 0 >+#if UPPERLOCK > if ((un->un_flags & UN_ULOCK) && un->un_uppervp) { > un->un_flags &= ~UN_ULOCK; > VOP_UNLOCK(un->un_uppervp, 0, p); >@@ -1748,7 +1835,7 @@ > union_lock(ap) > struct vop_lock_args *ap; > { >-#if 0 >+#if UPPERLOCK > struct vnode *vp = ap->a_vp; > struct proc *p = ap->a_p; > int flags = ap->a_flags; >@@ -1757,7 +1844,7 @@ > int error; > > error = vop_stdlock(ap); >-#if 0 >+#if UPPERLOCK > un = VTOUNION(vp); > > if (error == 0) { >@@ -1800,11 +1887,14 @@ > { > struct union_node *un = VTOUNION(ap->a_vp); > int error; >+#if UPPERLOCK >+ struct proc *p = ap->a_p; >+#endif > > KASSERT((un->un_uppervp == NULL || un->un_uppervp->v_usecount > 0), ("uppervp usecount is 0")); > > error = vop_stdunlock(ap); >-#if 0 >+#if UPPERLOCK > > /* > * If no exclusive locks remain and we are holding an uppervp lock,
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 27250
: 14505