2005-01-06 18:10:42 +00:00
|
|
|
/*-
|
1997-02-10 02:22:35 +00:00
|
|
|
* Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
|
|
|
|
* Copyright (c) 1992, 1993, 1994, 1995
|
2006-12-02 19:35:56 +00:00
|
|
|
* The Regents of the University of California.
|
2012-05-01 07:46:30 +00:00
|
|
|
* Copyright (c) 2005, 2006, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
|
|
|
|
* Copyright (c) 2006, 2012 Daichi Goto <daichi@freebsd.org>
|
2006-12-02 19:35:56 +00:00
|
|
|
* All rights reserved.
|
1994-05-24 10:09:53 +00:00
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Jan-Simon Pendry.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1997-02-10 02:22:35 +00:00
|
|
|
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
|
1999-08-28 01:08:13 +00:00
|
|
|
* $FreeBSD$
|
2006-12-02 19:35:56 +00:00
|
|
|
*
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <sys/conf.h>
|
1997-02-12 14:31:11 +00:00
|
|
|
#include <sys/kernel.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/mount.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <sys/mutex.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/namei.h>
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
#include <sys/sysctl.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/kdb.h>
|
|
|
|
#include <sys/fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/dirent.h>
|
|
|
|
#include <sys/proc.h>
|
2006-12-02 22:30:30 +00:00
|
|
|
#include <sys/bio.h>
|
|
|
|
#include <sys/buf.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2001-05-23 09:42:29 +00:00
|
|
|
#include <fs/unionfs/union.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
#include <vm/vm.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <vm/vm_extern.h>
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
#include <vm/vm_object.h>
|
2006-12-02 19:35:56 +00:00
|
|
|
#include <vm/vnode_pager.h>
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
#if 0
|
|
|
|
#define UNIONFS_INTERNAL_DEBUG(msg, args...) printf(msg, ## args)
|
|
|
|
#define UNIONFS_IDBG_RENAME
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
#else
|
2006-12-02 19:35:56 +00:00
|
|
|
#define UNIONFS_INTERNAL_DEBUG(msg, args...)
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
#define KASSERT_UNIONFS_VNODE(vp) \
|
|
|
|
KASSERT(((vp)->v_op == &unionfs_vnodeops), \
|
|
|
|
("unionfs: it is not unionfs-vnode"))
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
static int
|
2007-10-14 13:46:11 +00:00
|
|
|
unionfs_lookup(struct vop_cachedlookup_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int iswhiteout;
|
|
|
|
int lockflag;
|
|
|
|
int error , uerror, lerror;
|
|
|
|
u_long nameiop;
|
|
|
|
u_long cnflags, cnflagsbk;
|
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp;
|
|
|
|
struct vattr va;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
iswhiteout = 0;
|
|
|
|
lockflag = 0;
|
|
|
|
error = uerror = lerror = ENOENT;
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
nameiop = cnp->cn_nameiop;
|
|
|
|
cnflags = cnp->cn_flags;
|
|
|
|
dvp = ap->a_dvp;
|
|
|
|
dunp = VTOUNIONFS(dvp);
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
ldvp = dunp->un_lowervp;
|
|
|
|
vp = uvp = lvp = NULLVP;
|
|
|
|
td = curthread;
|
|
|
|
*(ap->a_vpp) = NULLVP;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n", nameiop, cnflags, cnp->cn_nameptr);
|
|
|
|
|
|
|
|
if (dvp->v_type != VDIR)
|
|
|
|
return (ENOTDIR);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* If read-only and op is not LOOKUP, will return EROFS.
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if ((cnflags & ISLASTCN) &&
|
|
|
|
(dvp->v_mount->mnt_flag & MNT_RDONLY) &&
|
|
|
|
LOOKUP != nameiop)
|
|
|
|
return (EROFS);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* lookup dotdot
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if (cnflags & ISDOTDOT) {
|
|
|
|
if (LOOKUP != nameiop && udvp == NULLVP)
|
|
|
|
return (EROFS);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (udvp != NULLVP) {
|
|
|
|
dtmpvp = udvp;
|
|
|
|
if (ldvp != NULLVP)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ldvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
dtmpvp = ldvp;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = VOP_LOOKUP(dtmpvp, &vp, cnp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (dtmpvp == udvp && ldvp != NULLVP) {
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(udvp, LK_RELEASE);
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error == 0) {
|
|
|
|
/*
|
|
|
|
* Exchange lock and reference from vp to
|
|
|
|
* dunp->un_dvp. vp is upper/lower vnode, but it
|
|
|
|
* will need to return the unionfs vnode.
|
|
|
|
*/
|
|
|
|
if (nameiop == DELETE || nameiop == RENAME ||
|
|
|
|
(cnp->cn_lkflags & LK_TYPE_MASK))
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(vp);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(dvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
*(ap->a_vpp) = dunp->un_dvp;
|
|
|
|
vref(dunp->un_dvp);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (nameiop == DELETE || nameiop == RENAME)
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(dunp->un_dvp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
else if (cnp->cn_lkflags & LK_TYPE_MASK)
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(dunp->un_dvp, cnp->cn_lkflags |
|
|
|
|
LK_RETRY);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
|
2014-12-18 10:01:12 +00:00
|
|
|
} else if (error == ENOENT && (cnflags & MAKEENTRY) != 0)
|
2007-10-14 13:46:11 +00:00
|
|
|
cache_enter(dvp, NULLVP, cnp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
|
1997-09-04 03:14:49 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
return (error);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* lookup upper layer
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if (udvp != NULLVP) {
|
|
|
|
uerror = VOP_LOOKUP(udvp, &uvp, cnp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uerror == 0) {
|
|
|
|
if (udvp == uvp) { /* is dot */
|
|
|
|
vrele(uvp);
|
|
|
|
*(ap->a_vpp) = dvp;
|
|
|
|
vref(dvp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", uerror);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
return (uerror);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
if (nameiop == DELETE || nameiop == RENAME ||
|
|
|
|
(cnp->cn_lkflags & LK_TYPE_MASK))
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(uvp, LK_RELEASE);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* check whiteout */
|
|
|
|
if (uerror == ENOENT || uerror == EJUSTRETURN)
|
|
|
|
if (cnp->cn_flags & ISWHITEOUT)
|
|
|
|
iswhiteout = 1; /* don't lookup lower */
|
|
|
|
if (iswhiteout == 0 && ldvp != NULLVP)
|
2008-08-28 15:23:18 +00:00
|
|
|
if (!VOP_GETATTR(udvp, &va, cnp->cn_cred) &&
|
2006-12-02 19:35:56 +00:00
|
|
|
(va.va_flags & OPAQUE))
|
|
|
|
iswhiteout = 1; /* don't lookup lower */
|
|
|
|
#if 0
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: debug: whiteout=%d, path=%s\n", iswhiteout, cnp->cn_nameptr);
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* lookup lower layer
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ldvp != NULLVP && !(cnflags & DOWHITEOUT) && iswhiteout == 0) {
|
|
|
|
/* always op is LOOKUP */
|
1994-05-24 10:09:53 +00:00
|
|
|
cnp->cn_nameiop = LOOKUP;
|
2006-12-02 19:35:56 +00:00
|
|
|
cnflagsbk = cnp->cn_flags;
|
|
|
|
cnp->cn_flags = cnflags;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
lerror = VOP_LOOKUP(ldvp, &lvp, cnp);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
cnp->cn_nameiop = nameiop;
|
2006-12-02 19:35:56 +00:00
|
|
|
if (udvp != NULLVP && (uerror == 0 || uerror == EJUSTRETURN))
|
|
|
|
cnp->cn_flags = cnflagsbk;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (lerror == 0) {
|
|
|
|
if (ldvp == lvp) { /* is dot */
|
|
|
|
if (uvp != NULLVP)
|
|
|
|
vrele(uvp); /* no need? */
|
|
|
|
vrele(lvp);
|
|
|
|
*(ap->a_vpp) = dvp;
|
|
|
|
vref(dvp);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", lerror);
|
|
|
|
|
|
|
|
return (lerror);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
if (cnp->cn_lkflags & LK_TYPE_MASK)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(lvp, LK_RELEASE);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* check lookup result
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp == NULLVP && lvp == NULLVP) {
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n",
|
|
|
|
(udvp != NULLVP ? uerror : lerror));
|
|
|
|
return (udvp != NULLVP ? uerror : lerror);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/*
|
|
|
|
* check vnode type
|
|
|
|
*/
|
|
|
|
if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) {
|
|
|
|
vrele(lvp);
|
|
|
|
lvp = NULLVP;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* check shadow dir
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP &&
|
|
|
|
lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR &&
|
|
|
|
!(dvp->v_mount->mnt_flag & MNT_RDONLY) &&
|
|
|
|
(1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) {
|
|
|
|
/* get unionfs vnode in order to create a new shadow dir. */
|
|
|
|
error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp,
|
|
|
|
cnp, td);
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_lookup_out;
|
|
|
|
|
|
|
|
if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK))
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2008-02-25 18:45:57 +00:00
|
|
|
if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) {
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
lockflag = 1;
|
|
|
|
}
|
|
|
|
error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount),
|
|
|
|
udvp, VTOUNIONFS(vp), cnp, td);
|
|
|
|
if (lockflag != 0)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0) {
|
|
|
|
UNIONFSDEBUG("unionfs_lookup: Unable to create shadow dir.");
|
|
|
|
if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE)
|
|
|
|
vput(vp);
|
|
|
|
else
|
|
|
|
vrele(vp);
|
|
|
|
goto unionfs_lookup_out;
|
|
|
|
}
|
|
|
|
if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED)
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_SHARED | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* get unionfs vnode.
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
else {
|
|
|
|
if (uvp != NULLVP)
|
|
|
|
error = uerror;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
else
|
2006-12-02 19:35:56 +00:00
|
|
|
error = lerror;
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_lookup_out;
|
2008-11-25 03:18:35 +00:00
|
|
|
/*
|
|
|
|
* get socket vnode.
|
|
|
|
*/
|
|
|
|
if (uvp != NULLVP && uvp->v_type == VSOCK) {
|
|
|
|
vp = uvp;
|
|
|
|
vref(vp);
|
|
|
|
if (cnp->cn_lkflags & LK_TYPE_MASK)
|
|
|
|
vn_lock(vp, cnp->cn_lkflags | LK_RETRY);
|
|
|
|
}
|
|
|
|
else if (lvp != NULLVP && lvp->v_type == VSOCK) {
|
|
|
|
vp = lvp;
|
|
|
|
vref(vp);
|
|
|
|
if (cnp->cn_lkflags & LK_TYPE_MASK)
|
|
|
|
vn_lock(vp, cnp->cn_lkflags | LK_RETRY);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* get unionfs vnode.
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
error = unionfs_nodeget(dvp->v_mount, uvp, lvp,
|
|
|
|
dvp, &vp, cnp, td);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0) {
|
|
|
|
UNIONFSDEBUG("unionfs_lookup: Unable to create unionfs vnode.");
|
|
|
|
goto unionfs_lookup_out;
|
|
|
|
}
|
|
|
|
if ((nameiop == DELETE || nameiop == RENAME) &&
|
|
|
|
(cnp->cn_lkflags & LK_TYPE_MASK) == 0)
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
*(ap->a_vpp) = vp;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
if ((cnflags & MAKEENTRY) && vp->v_type != VSOCK)
|
2007-10-14 13:46:11 +00:00
|
|
|
cache_enter(dvp, vp, cnp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_lookup_out:
|
|
|
|
if (uvp != NULLVP)
|
|
|
|
vrele(uvp);
|
|
|
|
if (lvp != NULLVP)
|
|
|
|
vrele(lvp);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2014-12-18 10:01:12 +00:00
|
|
|
if (error == ENOENT && (cnflags & MAKEENTRY) != 0)
|
2007-10-14 13:46:11 +00:00
|
|
|
cache_enter(dvp, NULLVP, cnp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
|
1998-01-18 07:56:41 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_create(struct vop_create_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *vp;
|
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n");
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
error = EROFS;
|
|
|
|
|
|
|
|
if (udvp != NULLVP) {
|
2008-11-25 03:18:35 +00:00
|
|
|
error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap);
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_create_abort;
|
|
|
|
|
|
|
|
if (vp->v_type == VSOCK)
|
|
|
|
*(ap->a_vpp) = vp;
|
|
|
|
else {
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
|
2008-01-13 14:44:15 +00:00
|
|
|
ap->a_dvp, ap->a_vpp, cnp, curthread);
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(vp);
|
1998-05-07 04:58:58 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
unionfs_create_abort:
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error);
|
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_whiteout(struct vop_whiteout_args *ap)
|
1997-02-10 02:22:35 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct vnode *udvp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
|
|
|
|
if (udvp != NULLVP) {
|
|
|
|
switch (ap->a_flags) {
|
|
|
|
case CREATE:
|
|
|
|
case DELETE:
|
|
|
|
case LOOKUP:
|
|
|
|
error = VOP_WHITEOUT(udvp, cnp, ap->a_flags);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2003-06-15 02:21:13 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: leave (%d)\n", error);
|
|
|
|
|
2003-06-15 02:21:13 +00:00
|
|
|
return (error);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_mknod(struct vop_mknod_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *vp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_mknod: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
error = EROFS;
|
|
|
|
|
|
|
|
if (udvp != NULLVP) {
|
2008-11-25 03:18:35 +00:00
|
|
|
error = VOP_MKNOD(udvp, &vp, cnp, ap->a_vap);
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_mknod_abort;
|
|
|
|
|
|
|
|
if (vp->v_type == VSOCK)
|
|
|
|
*(ap->a_vpp) = vp;
|
|
|
|
else {
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
|
2008-01-13 14:44:15 +00:00
|
|
|
ap->a_dvp, ap->a_vpp, cnp, curthread);
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(vp);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
unionfs_mknod_abort:
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_mknod: leave (%d)\n", error);
|
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_open(struct vop_open_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct vnode *targetvp;
|
|
|
|
struct ucred *cred;
|
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_open: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
targetvp = NULLVP;
|
|
|
|
cred = ap->a_cred;
|
|
|
|
td = ap->a_td;
|
|
|
|
|
|
|
|
unionfs_get_node_status(unp, td, &unsp);
|
|
|
|
|
|
|
|
if (unsp->uns_lower_opencnt > 0 || unsp->uns_upper_opencnt > 0) {
|
|
|
|
/* vnode is already opend. */
|
|
|
|
if (unsp->uns_upper_opencnt > 0)
|
|
|
|
targetvp = uvp;
|
|
|
|
else
|
|
|
|
targetvp = lvp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (targetvp == lvp &&
|
|
|
|
(ap->a_mode & FWRITE) && lvp->v_type == VREG)
|
|
|
|
targetvp = NULLVP;
|
|
|
|
}
|
|
|
|
if (targetvp == NULLVP) {
|
|
|
|
if (uvp == NULLVP) {
|
|
|
|
if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) {
|
|
|
|
error = unionfs_copyfile(unp,
|
|
|
|
!(ap->a_mode & O_TRUNC), cred, td);
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_open_abort;
|
|
|
|
targetvp = uvp = unp->un_uppervp;
|
|
|
|
} else
|
|
|
|
targetvp = lvp;
|
|
|
|
} else
|
|
|
|
targetvp = uvp;
|
|
|
|
}
|
|
|
|
|
2007-05-31 11:51:53 +00:00
|
|
|
error = VOP_OPEN(targetvp, ap->a_mode, cred, td, ap->a_fp);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error == 0) {
|
|
|
|
if (targetvp == uvp) {
|
|
|
|
if (uvp->v_type == VDIR && lvp != NULLVP &&
|
|
|
|
unsp->uns_lower_opencnt <= 0) {
|
|
|
|
/* open lower for readdir */
|
2007-05-31 11:51:53 +00:00
|
|
|
error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0) {
|
|
|
|
VOP_CLOSE(uvp, ap->a_mode, cred, td);
|
|
|
|
goto unionfs_open_abort;
|
|
|
|
}
|
|
|
|
unsp->uns_node_flag |= UNS_OPENL_4_READDIR;
|
|
|
|
unsp->uns_lower_opencnt++;
|
|
|
|
}
|
|
|
|
unsp->uns_upper_opencnt++;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
} else {
|
2006-12-02 19:35:56 +00:00
|
|
|
unsp->uns_lower_opencnt++;
|
|
|
|
unsp->uns_lower_openmode = ap->a_mode;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
ap->a_vp->v_object = targetvp->v_object;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_open_abort:
|
|
|
|
if (error != 0)
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_open: leave (%d)\n", error);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_close(struct vop_close_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
int locked;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct ucred *cred;
|
|
|
|
struct thread *td;
|
2012-05-01 07:46:30 +00:00
|
|
|
struct vnode *vp;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct vnode *ovp;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_close: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
locked = 0;
|
2012-05-01 07:46:30 +00:00
|
|
|
vp = ap->a_vp;
|
|
|
|
unp = VTOUNIONFS(vp);
|
2006-12-02 19:35:56 +00:00
|
|
|
cred = ap->a_cred;
|
|
|
|
td = ap->a_td;
|
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
|
|
|
|
if (vn_lock(vp, LK_UPGRADE) != 0)
|
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
locked = 1;
|
|
|
|
}
|
|
|
|
unionfs_get_node_status(unp, td, &unsp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
printf("unionfs_close: warning: open count is 0\n");
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unp->un_uppervp != NULLVP)
|
|
|
|
ovp = unp->un_uppervp;
|
|
|
|
else
|
|
|
|
ovp = unp->un_lowervp;
|
|
|
|
} else if (unsp->uns_upper_opencnt > 0)
|
|
|
|
ovp = unp->un_uppervp;
|
|
|
|
else
|
|
|
|
ovp = unp->un_lowervp;
|
|
|
|
|
|
|
|
error = VOP_CLOSE(ovp, ap->a_fflag, cred, td);
|
|
|
|
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_close_abort;
|
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
vp->v_object = ovp->v_object;
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
if (ovp == unp->un_uppervp) {
|
|
|
|
unsp->uns_upper_opencnt--;
|
|
|
|
if (unsp->uns_upper_opencnt == 0) {
|
|
|
|
if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) {
|
|
|
|
VOP_CLOSE(unp->un_lowervp, FREAD, cred, td);
|
|
|
|
unsp->uns_node_flag &= ~UNS_OPENL_4_READDIR;
|
|
|
|
unsp->uns_lower_opencnt--;
|
|
|
|
}
|
|
|
|
if (unsp->uns_lower_opencnt > 0)
|
2012-05-01 07:46:30 +00:00
|
|
|
vp->v_object = unp->un_lowervp->v_object;
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
unsp->uns_lower_opencnt--;
|
|
|
|
|
|
|
|
unionfs_close_abort:
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
if (locked != 0)
|
2012-05-01 07:46:30 +00:00
|
|
|
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* Check the access mode toward shadow file/dir.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2008-10-28 13:44:11 +00:00
|
|
|
unionfs_check_corrected_access(accmode_t accmode,
|
2006-12-02 19:35:56 +00:00
|
|
|
struct vattr *va,
|
|
|
|
struct ucred *cred)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int count;
|
|
|
|
uid_t uid; /* upper side vnode's uid */
|
|
|
|
gid_t gid; /* upper side vnode's gid */
|
|
|
|
u_short vmode; /* upper side vnode's mode */
|
|
|
|
u_short mask;
|
|
|
|
|
|
|
|
mask = 0;
|
|
|
|
uid = va->va_uid;
|
|
|
|
gid = va->va_gid;
|
|
|
|
vmode = va->va_mode;
|
|
|
|
|
|
|
|
/* check owner */
|
|
|
|
if (cred->cr_uid == uid) {
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VEXEC)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IXUSR;
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VREAD)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IRUSR;
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VWRITE)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IWUSR;
|
|
|
|
return ((vmode & mask) == mask ? 0 : EACCES);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* check group */
|
|
|
|
count = 0;
|
2009-06-19 17:10:35 +00:00
|
|
|
if (groupmember(gid, cred)) {
|
|
|
|
if (accmode & VEXEC)
|
|
|
|
mask |= S_IXGRP;
|
|
|
|
if (accmode & VREAD)
|
|
|
|
mask |= S_IRGRP;
|
|
|
|
if (accmode & VWRITE)
|
|
|
|
mask |= S_IWGRP;
|
|
|
|
return ((vmode & mask) == mask ? 0 : EACCES);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check other */
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VEXEC)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IXOTH;
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VREAD)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IROTH;
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VWRITE)
|
2006-12-02 19:35:56 +00:00
|
|
|
mask |= S_IWOTH;
|
|
|
|
|
|
|
|
return ((vmode & mask) == mask ? 0 : EACCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
unionfs_access(struct vop_access_args *ap)
|
|
|
|
{
|
|
|
|
struct unionfs_mount *ump;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vattr va;
|
2008-10-28 13:44:11 +00:00
|
|
|
accmode_t accmode;
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_access: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
td = ap->a_td;
|
2008-10-28 13:44:11 +00:00
|
|
|
accmode = ap->a_accmode;
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EACCES;
|
|
|
|
|
2008-10-28 13:44:11 +00:00
|
|
|
if ((accmode & VWRITE) &&
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
(ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
|
1997-09-04 03:14:49 +00:00
|
|
|
switch (ap->a_vp->v_type) {
|
2006-12-02 19:35:56 +00:00
|
|
|
case VREG:
|
1999-01-27 22:42:27 +00:00
|
|
|
case VDIR:
|
|
|
|
case VLNK:
|
1997-09-04 03:14:49 +00:00
|
|
|
return (EROFS);
|
1999-01-27 22:42:27 +00:00
|
|
|
default:
|
|
|
|
break;
|
1997-09-04 03:14:49 +00:00
|
|
|
}
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp != NULLVP) {
|
2008-10-28 13:44:11 +00:00
|
|
|
error = VOP_ACCESS(uvp, accmode, ap->a_cred, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
return (error);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (lvp != NULLVP) {
|
2008-10-28 13:44:11 +00:00
|
|
|
if (accmode & VWRITE) {
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY) {
|
|
|
|
switch (ap->a_vp->v_type) {
|
|
|
|
case VREG:
|
|
|
|
case VDIR:
|
|
|
|
case VLNK:
|
|
|
|
return (EROFS);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) {
|
|
|
|
/* check shadow file/dir */
|
|
|
|
if (ump->um_copymode != UNIONFS_TRANSPARENT) {
|
|
|
|
error = unionfs_create_uppervattr(ump,
|
|
|
|
lvp, &va, ap->a_cred, td);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
error = unionfs_check_corrected_access(
|
2008-10-28 13:44:11 +00:00
|
|
|
accmode, &va, ap->a_cred);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
}
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
2011-10-10 21:32:08 +00:00
|
|
|
accmode &= ~(VWRITE | VAPPEND);
|
2008-10-28 13:44:11 +00:00
|
|
|
accmode |= VREAD; /* will copy to upper */
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2008-10-28 13:44:11 +00:00
|
|
|
error = VOP_ACCESS(lvp, accmode, ap->a_cred, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_getattr(struct vop_getattr_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_mount *ump;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vattr va;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getattr: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
2008-08-28 15:23:18 +00:00
|
|
|
td = curthread;
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
if (uvp != NULLVP) {
|
2008-08-28 15:23:18 +00:00
|
|
|
if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
|
|
|
|
ap->a_vap->va_mode, ap->a_vap->va_uid,
|
|
|
|
ap->a_vap->va_gid, error);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_GETATTR(lvp, ap->a_vap, ap->a_cred);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error == 0 && !(ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY)) {
|
|
|
|
/* correct the attr toward shadow file/dir. */
|
|
|
|
if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) {
|
|
|
|
unionfs_create_uppervattr_core(ump, ap->a_vap, &va, td);
|
|
|
|
ap->a_vap->va_mode = va.va_mode;
|
|
|
|
ap->a_vap->va_uid = va.va_uid;
|
|
|
|
ap->a_vap->va_gid = va.va_gid;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error == 0)
|
2004-10-05 16:53:37 +00:00
|
|
|
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
|
2004-10-02 17:17:04 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
|
|
|
|
ap->a_vap->va_mode, ap->a_vap->va_uid, ap->a_vap->va_gid, error);
|
|
|
|
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_setattr(struct vop_setattr_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vattr *vap;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
2008-08-28 15:23:18 +00:00
|
|
|
td = curthread;
|
2006-12-02 19:35:56 +00:00
|
|
|
vap = ap->a_vap;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-09-04 03:14:49 +00:00
|
|
|
if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
(vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
|
|
|
|
vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
|
2006-12-02 19:35:56 +00:00
|
|
|
vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL))
|
1997-09-04 03:14:49 +00:00
|
|
|
return (EROFS);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp == NULLVP && lvp->v_type == VREG) {
|
|
|
|
error = unionfs_copyfile(unp, (vap->va_size != 0),
|
|
|
|
ap->a_cred, td);
|
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2006-12-02 19:35:56 +00:00
|
|
|
uvp = unp->un_uppervp;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp != NULLVP)
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_SETATTR(uvp, vap, ap->a_cred);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_read(struct vop_read_args *ap)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *tvp;
|
|
|
|
|
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_read: enter\n"); */
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
|
|
|
|
|
|
|
error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
|
|
|
|
|
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_read: leave (%d)\n", error); */
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
unionfs_write(struct vop_write_args *ap)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *tvp;
|
|
|
|
|
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
|
|
|
|
|
|
|
error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
|
|
|
|
|
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_ioctl(struct vop_ioctl_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
int error;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct vnode *ovp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: enter\n");
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
unionfs_get_node_status(unp, ap->a_td, &unsp);
|
|
|
|
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ap->a_vp, LK_RELEASE);
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ovp == NULLVP)
|
|
|
|
return (EBADF);
|
|
|
|
|
|
|
|
error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag,
|
|
|
|
ap->a_cred, ap->a_td);
|
|
|
|
|
2009-04-10 10:52:19 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error);
|
1997-02-10 02:22:35 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_poll(struct vop_poll_args *ap)
|
1997-02-10 02:22:35 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct vnode *ovp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
unionfs_get_node_status(unp, ap->a_td, &unsp);
|
|
|
|
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ap->a_vp, LK_RELEASE);
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ovp == NULLVP)
|
|
|
|
return (EBADF);
|
|
|
|
|
|
|
|
return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td));
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_fsync(struct vop_fsync_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct vnode *ovp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
unionfs_get_node_status(unp, ap->a_td, &unsp);
|
|
|
|
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ovp == NULLVP)
|
|
|
|
return (EBADF);
|
|
|
|
|
|
|
|
return (VOP_FSYNC(ovp, ap->a_waitfor, ap->a_td));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_remove(struct vop_remove_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
2008-11-25 03:18:35 +00:00
|
|
|
char *path;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct unionfs_node *unp;
|
2007-10-14 13:55:38 +00:00
|
|
|
struct unionfs_mount *ump;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
2008-11-25 03:18:35 +00:00
|
|
|
struct vnode *vp;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct componentname *cnp;
|
2008-11-25 03:18:35 +00:00
|
|
|
struct componentname cn;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n");
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
td = curthread;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
if (ap->a_vp->v_op != &unionfs_vnodeops) {
|
|
|
|
if (ap->a_vp->v_type != VSOCK)
|
|
|
|
return (EINVAL);
|
|
|
|
ump = NULL;
|
|
|
|
vp = uvp = lvp = NULLVP;
|
|
|
|
/* search vnode */
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ap->a_vp, LK_RELEASE);
|
2008-11-25 03:18:35 +00:00
|
|
|
error = unionfs_relookup(udvp, &vp, cnp, &cn, td,
|
|
|
|
cnp->cn_nameptr, strlen(cnp->cn_nameptr), DELETE);
|
|
|
|
if (error != 0 && error != ENOENT) {
|
|
|
|
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error == 0 && vp == ap->a_vp) {
|
|
|
|
/* target vnode in upper */
|
|
|
|
uvp = vp;
|
|
|
|
vrele(vp);
|
|
|
|
path = NULL;
|
|
|
|
} else {
|
|
|
|
/* target vnode in lower */
|
|
|
|
if (vp != NULLVP) {
|
|
|
|
if (udvp == vp)
|
|
|
|
vrele(vp);
|
|
|
|
else
|
|
|
|
vput(vp);
|
|
|
|
}
|
|
|
|
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
|
|
|
|
lvp = ap->a_vp;
|
|
|
|
path = ap->a_cnp->cn_nameptr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
path = unp->un_path;
|
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (udvp == NULLVP)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (uvp != NULLVP) {
|
2008-11-25 03:18:35 +00:00
|
|
|
/*
|
|
|
|
* XXX: if the vnode type is VSOCK, it will create whiteout
|
|
|
|
* after remove.
|
|
|
|
*/
|
|
|
|
if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS ||
|
|
|
|
lvp != NULLVP)
|
2007-10-14 13:55:38 +00:00
|
|
|
cnp->cn_flags |= DOWHITEOUT;
|
2006-12-02 19:35:56 +00:00
|
|
|
error = VOP_REMOVE(udvp, uvp, cnp);
|
|
|
|
} else if (lvp != NULLVP)
|
2008-11-25 03:18:35 +00:00
|
|
|
error = unionfs_mkwhiteout(udvp, cnp, td, path);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_link(struct vop_link_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
int needrelookup;
|
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_link: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_tdvp);
|
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
needrelookup = 0;
|
|
|
|
dunp = VTOUNIONFS(ap->a_tdvp);
|
|
|
|
unp = NULL;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
uvp = NULLVP;
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
td = curthread;
|
|
|
|
|
|
|
|
if (udvp == NULLVP)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (ap->a_vp->v_op != &unionfs_vnodeops)
|
|
|
|
uvp = ap->a_vp;
|
|
|
|
else {
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
|
|
|
|
if (unp->un_uppervp == NULLVP) {
|
|
|
|
if (ap->a_vp->v_type != VREG)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
error = unionfs_copyfile(unp, 1, cnp->cn_cred, td);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
needrelookup = 1;
|
|
|
|
}
|
|
|
|
uvp = unp->un_uppervp;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (needrelookup != 0)
|
|
|
|
error = unionfs_relookup_for_create(ap->a_tdvp, cnp, td);
|
|
|
|
|
|
|
|
if (error == 0)
|
|
|
|
error = VOP_LINK(udvp, uvp, cnp);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_link: leave (%d)\n", error);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_rename(struct vop_rename_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct vnode *fdvp;
|
|
|
|
struct vnode *fvp;
|
|
|
|
struct componentname *fcnp;
|
|
|
|
struct vnode *tdvp;
|
|
|
|
struct vnode *tvp;
|
|
|
|
struct componentname *tcnp;
|
|
|
|
struct vnode *ltdvp;
|
|
|
|
struct vnode *ltvp;
|
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
/* rename target vnodes */
|
|
|
|
struct vnode *rfdvp;
|
|
|
|
struct vnode *rfvp;
|
|
|
|
struct vnode *rtdvp;
|
|
|
|
struct vnode *rtvp;
|
|
|
|
|
|
|
|
int needrelookup;
|
|
|
|
struct unionfs_mount *ump;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n");
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
fdvp = ap->a_fdvp;
|
|
|
|
fvp = ap->a_fvp;
|
|
|
|
fcnp = ap->a_fcnp;
|
|
|
|
tdvp = ap->a_tdvp;
|
|
|
|
tvp = ap->a_tvp;
|
|
|
|
tcnp = ap->a_tcnp;
|
|
|
|
ltdvp = NULLVP;
|
|
|
|
ltvp = NULLVP;
|
|
|
|
td = curthread;
|
|
|
|
rfdvp = fdvp;
|
|
|
|
rfvp = fvp;
|
|
|
|
rtdvp = tdvp;
|
|
|
|
rtvp = tvp;
|
|
|
|
needrelookup = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (!(fcnp->cn_flags & HASBUF) || !(tcnp->cn_flags & HASBUF))
|
|
|
|
panic("unionfs_rename: no name");
|
|
|
|
#endif
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* check for cross device rename */
|
|
|
|
if (fvp->v_mount != tdvp->v_mount ||
|
|
|
|
(tvp != NULLVP && fvp->v_mount != tvp->v_mount)) {
|
2008-11-25 03:18:35 +00:00
|
|
|
if (fvp->v_op != &unionfs_vnodeops)
|
|
|
|
error = ENODEV;
|
|
|
|
else
|
|
|
|
error = EXDEV;
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Renaming a file to itself has no effect. */
|
|
|
|
if (fvp == tvp)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* from/to vnode is unionfs node.
|
|
|
|
*/
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(fdvp);
|
|
|
|
KASSERT_UNIONFS_VNODE(fvp);
|
|
|
|
KASSERT_UNIONFS_VNODE(tdvp);
|
|
|
|
if (tvp != NULLVP)
|
|
|
|
KASSERT_UNIONFS_VNODE(tvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(fdvp);
|
|
|
|
#ifdef UNIONFS_IDBG_RENAME
|
|
|
|
UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n", fdvp, unp->un_uppervp, unp->un_lowervp);
|
|
|
|
#endif
|
|
|
|
if (unp->un_uppervp == NULLVP) {
|
|
|
|
error = ENODEV;
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
rfdvp = unp->un_uppervp;
|
|
|
|
vref(rfdvp);
|
|
|
|
|
|
|
|
unp = VTOUNIONFS(fvp);
|
|
|
|
#ifdef UNIONFS_IDBG_RENAME
|
|
|
|
UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n", fvp, unp->un_uppervp, unp->un_lowervp);
|
|
|
|
#endif
|
|
|
|
ump = MOUNTTOUNIONFSMOUNT(fvp->v_mount);
|
|
|
|
if (unp->un_uppervp == NULLVP) {
|
|
|
|
switch (fvp->v_type) {
|
|
|
|
case VREG:
|
2008-01-10 01:10:58 +00:00
|
|
|
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_rename_abort;
|
|
|
|
error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td);
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(fvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
break;
|
|
|
|
case VDIR:
|
2008-01-10 01:10:58 +00:00
|
|
|
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_rename_abort;
|
|
|
|
error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td);
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(fvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = ENODEV;
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
needrelookup = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unp->un_lowervp != NULLVP)
|
|
|
|
fcnp->cn_flags |= DOWHITEOUT;
|
|
|
|
rfvp = unp->un_uppervp;
|
|
|
|
vref(rfvp);
|
|
|
|
|
|
|
|
unp = VTOUNIONFS(tdvp);
|
|
|
|
#ifdef UNIONFS_IDBG_RENAME
|
|
|
|
UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n", tdvp, unp->un_uppervp, unp->un_lowervp);
|
|
|
|
#endif
|
|
|
|
if (unp->un_uppervp == NULLVP) {
|
|
|
|
error = ENODEV;
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
rtdvp = unp->un_uppervp;
|
|
|
|
ltdvp = unp->un_lowervp;
|
|
|
|
vref(rtdvp);
|
|
|
|
|
|
|
|
if (tdvp == tvp) {
|
|
|
|
rtvp = rtdvp;
|
|
|
|
vref(rtvp);
|
|
|
|
} else if (tvp != NULLVP) {
|
|
|
|
unp = VTOUNIONFS(tvp);
|
|
|
|
#ifdef UNIONFS_IDBG_RENAME
|
|
|
|
UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n", tvp, unp->un_uppervp, unp->un_lowervp);
|
|
|
|
#endif
|
|
|
|
if (unp->un_uppervp == NULLVP)
|
|
|
|
rtvp = NULLVP;
|
|
|
|
else {
|
|
|
|
if (tvp->v_type == VDIR) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
rtvp = unp->un_uppervp;
|
|
|
|
ltvp = unp->un_lowervp;
|
|
|
|
vref(rtvp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-25 09:44:47 +00:00
|
|
|
if (rfvp == rtvp)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (needrelookup != 0) {
|
2008-01-10 01:10:58 +00:00
|
|
|
if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_rename_abort;
|
|
|
|
error = unionfs_relookup_for_delete(fdvp, fcnp, td);
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(fdvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
|
|
|
|
/* Locke of tvp is canceled in order to avoid recursive lock. */
|
|
|
|
if (tvp != NULLVP && tvp != tdvp)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(tvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
error = unionfs_relookup_for_rename(tdvp, tcnp, td);
|
|
|
|
if (tvp != NULLVP && tvp != tdvp)
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_rename_abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);
|
|
|
|
|
2007-10-14 13:46:11 +00:00
|
|
|
if (error == 0) {
|
|
|
|
if (rtvp != NULLVP && rtvp->v_type == VDIR)
|
|
|
|
cache_purge(tdvp);
|
|
|
|
if (fvp->v_type == VDIR && fdvp != tdvp)
|
|
|
|
cache_purge(fdvp);
|
|
|
|
}
|
|
|
|
|
2007-10-14 13:47:44 +00:00
|
|
|
if (ltdvp != NULLVP)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ltdvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (tdvp != rtdvp)
|
|
|
|
vrele(tdvp);
|
2007-10-14 13:47:44 +00:00
|
|
|
if (ltvp != NULLVP)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(ltvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (tvp != rtvp && tvp != NULLVP) {
|
|
|
|
if (rtvp == NULLVP)
|
|
|
|
vput(tvp);
|
2004-01-16 22:55:25 +00:00
|
|
|
else
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(tvp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2008-04-25 09:44:47 +00:00
|
|
|
if (fdvp != rfdvp)
|
|
|
|
vrele(fdvp);
|
|
|
|
if (fvp != rfvp)
|
|
|
|
vrele(fvp);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
unionfs_rename_abort:
|
2008-04-25 09:44:47 +00:00
|
|
|
vput(tdvp);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (tdvp != rtdvp)
|
|
|
|
vrele(rtdvp);
|
|
|
|
if (tvp != NULLVP) {
|
|
|
|
if (tdvp != tvp)
|
|
|
|
vput(tvp);
|
|
|
|
else
|
|
|
|
vrele(tvp);
|
|
|
|
}
|
2008-04-25 09:44:47 +00:00
|
|
|
if (tvp != rtvp && rtvp != NULLVP)
|
|
|
|
vrele(rtvp);
|
|
|
|
if (fdvp != rfdvp)
|
|
|
|
vrele(rfdvp);
|
|
|
|
if (fvp != rfvp)
|
|
|
|
vrele(rfvp);
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(fdvp);
|
|
|
|
vrele(fvp);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
static int
|
|
|
|
unionfs_mkdir(struct vop_mkdir_args *ap)
|
|
|
|
{
|
|
|
|
int error;
|
2007-01-05 02:25:44 +00:00
|
|
|
int lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vattr va;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
cnp = ap->a_cnp;
|
2007-01-05 02:25:44 +00:00
|
|
|
lkflags = cnp->cn_lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
td = curthread;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
|
|
|
|
if (udvp != NULLVP) {
|
|
|
|
/* check opaque */
|
|
|
|
if (!(cnp->cn_flags & ISWHITEOUT)) {
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_GETATTR(udvp, &va, cnp->cn_cred);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
if (va.va_flags & OPAQUE)
|
|
|
|
cnp->cn_flags |= ISWHITEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) {
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(uvp, LK_RELEASE);
|
2007-01-05 02:25:44 +00:00
|
|
|
cnp->cn_lkflags = LK_EXCLUSIVE;
|
2006-12-02 19:35:56 +00:00
|
|
|
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP,
|
|
|
|
ap->a_dvp, ap->a_vpp, cnp, td);
|
2007-01-05 02:25:44 +00:00
|
|
|
cnp->cn_lkflags = lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(uvp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_rmdir(struct vop_rmdir_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct unionfs_node *unp;
|
2007-10-14 13:55:38 +00:00
|
|
|
struct unionfs_mount *ump;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct componentname *cnp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
cnp = ap->a_cnp;
|
|
|
|
td = curthread;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
|
|
|
|
if (udvp == NULLVP)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (udvp == uvp)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
if (uvp != NULLVP) {
|
|
|
|
if (lvp != NULLVP) {
|
|
|
|
error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td);
|
|
|
|
if (error != 0)
|
2002-09-19 13:32:45 +00:00
|
|
|
return (error);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
2007-10-14 13:55:38 +00:00
|
|
|
ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
|
|
|
|
if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
|
|
|
|
cnp->cn_flags |= DOWHITEOUT;
|
2012-05-01 07:46:30 +00:00
|
|
|
error = unionfs_relookup_for_delete(ap->a_dvp, cnp, td);
|
|
|
|
if (!error)
|
|
|
|
error = VOP_RMDIR(udvp, uvp, cnp);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
else if (lvp != NULLVP)
|
|
|
|
error = unionfs_mkwhiteout(udvp, cnp, td, unp->un_path);
|
|
|
|
|
2007-10-14 13:46:11 +00:00
|
|
|
if (error == 0) {
|
|
|
|
cache_purge(ap->a_dvp);
|
|
|
|
cache_purge(ap->a_vp);
|
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
unionfs_symlink(struct vop_symlink_args *ap)
|
|
|
|
{
|
|
|
|
int error;
|
2007-01-05 02:25:44 +00:00
|
|
|
int lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *dunp;
|
|
|
|
struct componentname *cnp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vnode *udvp;
|
|
|
|
struct vnode *uvp;
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n");
|
1998-05-07 04:58:58 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_dvp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
dunp = VTOUNIONFS(ap->a_dvp);
|
|
|
|
cnp = ap->a_cnp;
|
2007-01-05 02:25:44 +00:00
|
|
|
lkflags = cnp->cn_lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
td = curthread;
|
|
|
|
udvp = dunp->un_uppervp;
|
|
|
|
|
|
|
|
if (udvp != NULLVP) {
|
|
|
|
error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target);
|
|
|
|
if (error == 0) {
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(uvp, LK_RELEASE);
|
2007-01-05 02:25:44 +00:00
|
|
|
cnp->cn_lkflags = LK_EXCLUSIVE;
|
2006-12-02 19:35:56 +00:00
|
|
|
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP,
|
|
|
|
ap->a_dvp, ap->a_vpp, cnp, td);
|
2007-01-05 02:25:44 +00:00
|
|
|
cnp->cn_lkflags = lkflags;
|
2006-12-02 19:35:56 +00:00
|
|
|
vrele(uvp);
|
|
|
|
}
|
|
|
|
}
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error);
|
1998-05-07 04:58:58 +00:00
|
|
|
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_readdir(struct vop_readdir_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
int eofflag;
|
2007-01-05 02:25:44 +00:00
|
|
|
int locked;
|
2012-05-01 07:46:30 +00:00
|
|
|
int uio_offset_bk;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct uio *uio;
|
2012-05-01 07:46:30 +00:00
|
|
|
struct vnode *vp;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
struct vattr va;
|
|
|
|
|
|
|
|
int ncookies_bk;
|
|
|
|
u_long *cookies_bk;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
eofflag = 0;
|
2007-01-05 02:25:44 +00:00
|
|
|
locked = 0;
|
2012-05-01 07:46:30 +00:00
|
|
|
uio_offset_bk = 0;
|
2006-12-02 19:35:56 +00:00
|
|
|
uio = ap->a_uio;
|
2012-05-01 07:46:30 +00:00
|
|
|
uvp = NULLVP;
|
|
|
|
lvp = NULLVP;
|
2006-12-02 19:35:56 +00:00
|
|
|
td = uio->uio_td;
|
|
|
|
ncookies_bk = 0;
|
|
|
|
cookies_bk = NULL;
|
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
vp = ap->a_vp;
|
|
|
|
if (vp->v_type != VDIR)
|
2006-12-02 19:35:56 +00:00
|
|
|
return (ENOTDIR);
|
|
|
|
|
2007-10-14 13:44:06 +00:00
|
|
|
/* check the open count. unionfs needs to open before readdir. */
|
2012-05-01 07:46:30 +00:00
|
|
|
if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
|
|
|
|
if (vn_lock(vp, LK_UPGRADE) != 0)
|
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2007-01-05 02:25:44 +00:00
|
|
|
locked = 1;
|
|
|
|
}
|
2012-05-01 07:46:30 +00:00
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
if (unp == NULL)
|
2007-10-14 13:44:06 +00:00
|
|
|
error = EBADF;
|
2012-05-01 07:46:30 +00:00
|
|
|
else {
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
unionfs_get_node_status(unp, td, &unsp);
|
|
|
|
if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) ||
|
|
|
|
(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) {
|
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
|
|
|
error = EBADF;
|
|
|
|
}
|
2007-10-14 13:44:06 +00:00
|
|
|
}
|
2012-05-01 07:46:30 +00:00
|
|
|
if (locked)
|
|
|
|
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
|
2007-10-14 13:44:06 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_readdir_exit;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
/* check opaque */
|
|
|
|
if (uvp != NULLVP && lvp != NULLVP) {
|
|
|
|
if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0)
|
|
|
|
goto unionfs_readdir_exit;
|
|
|
|
if (va.va_flags & OPAQUE)
|
|
|
|
lvp = NULLVP;
|
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* upper only */
|
|
|
|
if (uvp != NULLVP && lvp == NULLVP) {
|
2007-10-14 13:44:06 +00:00
|
|
|
error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,
|
|
|
|
ap->a_ncookies, ap->a_cookies);
|
|
|
|
unsp->uns_readdir_status = 0;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_readdir_exit;
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* lower only */
|
|
|
|
if (uvp == NULLVP && lvp != NULLVP) {
|
2007-10-14 13:44:06 +00:00
|
|
|
error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
|
|
|
|
ap->a_ncookies, ap->a_cookies);
|
|
|
|
unsp->uns_readdir_status = 2;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_readdir_exit;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* readdir upper and lower
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2007-10-14 13:50:58 +00:00
|
|
|
KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp"));
|
|
|
|
KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp"));
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uio->uio_offset == 0)
|
|
|
|
unsp->uns_readdir_status = 0;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unsp->uns_readdir_status == 0) {
|
|
|
|
/* read upper */
|
|
|
|
error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag,
|
|
|
|
ap->a_ncookies, ap->a_cookies);
|
|
|
|
|
2007-10-14 13:44:06 +00:00
|
|
|
if (error != 0 || eofflag == 0)
|
|
|
|
goto unionfs_readdir_exit;
|
2006-12-02 19:35:56 +00:00
|
|
|
unsp->uns_readdir_status = 1;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
/*
|
2012-05-01 07:46:30 +00:00
|
|
|
* UFS(and other FS) needs size of uio_resid larger than
|
2006-12-02 19:35:56 +00:00
|
|
|
* DIRBLKSIZ.
|
|
|
|
* size of DIRBLKSIZ equals DEV_BSIZE.
|
|
|
|
* (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h)
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
*/
|
2007-10-14 13:44:06 +00:00
|
|
|
if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1)))
|
|
|
|
goto unionfs_readdir_exit;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/*
|
2012-05-01 07:46:30 +00:00
|
|
|
* Backup cookies.
|
2006-12-02 19:35:56 +00:00
|
|
|
* It prepares to readdir in lower.
|
|
|
|
*/
|
|
|
|
if (ap->a_ncookies != NULL) {
|
|
|
|
ncookies_bk = *(ap->a_ncookies);
|
|
|
|
*(ap->a_ncookies) = 0;
|
|
|
|
}
|
|
|
|
if (ap->a_cookies != NULL) {
|
|
|
|
cookies_bk = *(ap->a_cookies);
|
|
|
|
*(ap->a_cookies) = NULL;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
/* initialize for readdir in lower */
|
|
|
|
if (unsp->uns_readdir_status == 1) {
|
|
|
|
unsp->uns_readdir_status = 2;
|
2012-05-01 07:46:30 +00:00
|
|
|
/*
|
|
|
|
* Backup uio_offset. See the comment after the
|
|
|
|
* VOP_READDIR call on the lower layer.
|
|
|
|
*/
|
|
|
|
uio_offset_bk = uio->uio_offset;
|
2006-12-02 19:35:56 +00:00
|
|
|
uio->uio_offset = 0;
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-09 16:34:37 +00:00
|
|
|
if (lvp == NULLVP) {
|
|
|
|
error = EBADF;
|
|
|
|
goto unionfs_readdir_exit;
|
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
/* read lower */
|
|
|
|
error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
|
|
|
|
ap->a_ncookies, ap->a_cookies);
|
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
/*
|
|
|
|
* We can't return an uio_offset of 0: this would trigger an
|
|
|
|
* infinite loop, because the next call to unionfs_readdir would
|
|
|
|
* always restart with the upper layer (uio_offset == 0) and
|
|
|
|
* always return some data.
|
|
|
|
*
|
|
|
|
* This happens when the lower layer root directory is removed.
|
|
|
|
* (A root directory deleting of unionfs should not be permitted.
|
|
|
|
* But current VFS can not do it.)
|
|
|
|
*/
|
|
|
|
if (uio->uio_offset == 0)
|
|
|
|
uio->uio_offset = uio_offset_bk;
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (cookies_bk != NULL) {
|
|
|
|
/* merge cookies */
|
|
|
|
int size;
|
|
|
|
u_long *newcookies, *pos;
|
|
|
|
|
|
|
|
size = *(ap->a_ncookies) + ncookies_bk;
|
|
|
|
newcookies = (u_long *) malloc(size * sizeof(u_long),
|
|
|
|
M_TEMP, M_WAITOK);
|
|
|
|
pos = newcookies;
|
|
|
|
|
|
|
|
memcpy(pos, cookies_bk, ncookies_bk * sizeof(u_long));
|
2012-05-03 07:22:29 +00:00
|
|
|
pos += ncookies_bk;
|
2006-12-02 19:35:56 +00:00
|
|
|
memcpy(pos, *(ap->a_cookies), *(ap->a_ncookies) * sizeof(u_long));
|
|
|
|
free(cookies_bk, M_TEMP);
|
|
|
|
free(*(ap->a_cookies), M_TEMP);
|
|
|
|
*(ap->a_ncookies) = size;
|
|
|
|
*(ap->a_cookies) = newcookies;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_readdir_exit:
|
2007-10-14 13:44:06 +00:00
|
|
|
if (error != 0 && ap->a_eofflag != NULL)
|
|
|
|
*(ap->a_eofflag) = 1;
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_readlink(struct vop_readlink_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n");
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
|
|
|
|
|
|
|
error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error);
|
1998-05-07 04:58:58 +00:00
|
|
|
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_getwritemount(struct vop_getwritemount_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *vp;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n");
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
vp = ap->a_vp;
|
|
|
|
|
|
|
|
if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY))
|
|
|
|
return (EACCES);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
uvp = UNIONFSVPTOUPPERVP(vp);
|
|
|
|
if (uvp == NULLVP && VREG == vp->v_type)
|
|
|
|
uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp);
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp != NULLVP)
|
|
|
|
error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp);
|
|
|
|
else {
|
|
|
|
VI_LOCK(vp);
|
|
|
|
if (vp->v_iflag & VI_FREE)
|
2004-01-16 22:55:25 +00:00
|
|
|
error = EOPNOTSUPP;
|
|
|
|
else
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EACCES;
|
|
|
|
VI_UNLOCK(vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_inactive(struct vop_inactive_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2007-10-14 13:46:11 +00:00
|
|
|
ap->a_vp->v_object = NULL;
|
2012-04-23 14:10:34 +00:00
|
|
|
vrecycle(ap->a_vp);
|
2006-12-02 19:35:56 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_reclaim(struct vop_reclaim_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */
|
|
|
|
|
2007-10-14 13:46:11 +00:00
|
|
|
unionfs_noderem(ap->a_vp, ap->a_td);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */
|
|
|
|
|
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_print(struct vop_print_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
/* struct unionfs_node_status *unsp; */
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
/* unionfs_get_node_status(unp, curthread, &unsp); */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n",
|
|
|
|
ap->a_vp, unp->un_uppervp, unp->un_lowervp);
|
|
|
|
/*
|
|
|
|
printf("unionfs opencnt: uppervp=%d, lowervp=%d\n",
|
|
|
|
unsp->uns_upper_opencnt, unsp->uns_lower_opencnt);
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unp->un_uppervp != NULLVP)
|
|
|
|
vprint("unionfs: upper", unp->un_uppervp);
|
|
|
|
if (unp->un_lowervp != NULLVP)
|
|
|
|
vprint("unionfs: lower", unp->un_lowervp);
|
|
|
|
|
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
static int
|
2012-05-01 07:46:30 +00:00
|
|
|
unionfs_islocked(struct vop_islocked_args *ap)
|
2000-07-11 22:07:57 +00:00
|
|
|
{
|
2012-05-01 07:46:30 +00:00
|
|
|
struct unionfs_node *unp;
|
2000-07-11 22:07:57 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
if (unp == NULL)
|
|
|
|
return (vop_stdislocked(ap));
|
|
|
|
|
|
|
|
if (unp->un_uppervp != NULLVP)
|
|
|
|
return (VOP_ISLOCKED(unp->un_uppervp));
|
|
|
|
if (unp->un_lowervp != NULLVP)
|
|
|
|
return (VOP_ISLOCKED(unp->un_lowervp));
|
|
|
|
return (vop_stdislocked(ap));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
unionfs_get_llt_revlock(struct vnode *vp, int flags)
|
|
|
|
{
|
|
|
|
int revlock;
|
|
|
|
|
|
|
|
revlock = 0;
|
|
|
|
|
|
|
|
switch (flags & LK_TYPE_MASK) {
|
|
|
|
case LK_SHARED:
|
|
|
|
if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
|
|
|
|
revlock = LK_UPGRADE;
|
|
|
|
else
|
|
|
|
revlock = LK_RELEASE;
|
|
|
|
break;
|
|
|
|
case LK_EXCLUSIVE:
|
|
|
|
case LK_UPGRADE:
|
|
|
|
revlock = LK_RELEASE;
|
|
|
|
break;
|
|
|
|
case LK_DOWNGRADE:
|
|
|
|
revlock = LK_UPGRADE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2001-05-17 04:58:25 +00:00
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
return (revlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The state of an acquired lock is adjusted similarly to
|
|
|
|
* the time of error generating.
|
|
|
|
* flags: LK_RELEASE or LK_UPGRADE
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
unionfs_revlock(struct vnode *vp, int flags)
|
|
|
|
{
|
|
|
|
if (flags & LK_RELEASE)
|
|
|
|
VOP_UNLOCK(vp, flags);
|
|
|
|
else {
|
|
|
|
/* UPGRADE */
|
|
|
|
if (vn_lock(vp, flags) != 0)
|
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2007-05-18 13:02:13 +00:00
|
|
|
unionfs_lock(struct vop_lock1_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
int flags;
|
|
|
|
int revlock;
|
2012-05-01 07:46:30 +00:00
|
|
|
int interlock;
|
2006-12-02 19:35:56 +00:00
|
|
|
int uhold;
|
2007-10-14 13:49:30 +00:00
|
|
|
struct mount *mp;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_mount *ump;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
2012-05-01 07:46:30 +00:00
|
|
|
interlock = 1;
|
2006-12-02 19:35:56 +00:00
|
|
|
uhold = 0;
|
|
|
|
flags = ap->a_flags;
|
|
|
|
vp = ap->a_vp;
|
|
|
|
|
|
|
|
if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK))
|
2012-05-01 07:46:30 +00:00
|
|
|
return (VOP_UNLOCK(vp, flags | LK_RELEASE));
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
if ((flags & LK_INTERLOCK) == 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_LOCK(vp);
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
mp = vp->v_mount;
|
|
|
|
if (mp == NULL)
|
|
|
|
goto unionfs_lock_null_vnode;
|
|
|
|
|
|
|
|
ump = MOUNTTOUNIONFSMOUNT(mp);
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(vp);
|
2007-10-14 13:49:30 +00:00
|
|
|
if (ump == NULL || unp == NULL)
|
2006-12-02 19:35:56 +00:00
|
|
|
goto unionfs_lock_null_vnode;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
uvp = unp->un_uppervp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0)
|
|
|
|
panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK);
|
|
|
|
|
2012-11-09 18:02:25 +00:00
|
|
|
if ((vp->v_iflag & VI_OWEINACT) != 0)
|
2007-10-14 13:49:30 +00:00
|
|
|
flags |= LK_NOWAIT;
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2006-12-02 19:35:56 +00:00
|
|
|
* Sometimes, lower or upper is already exclusive locked.
|
|
|
|
* (ex. vfs_domount: mounted vnode is already locked.)
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2006-12-02 19:35:56 +00:00
|
|
|
if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE &&
|
|
|
|
vp == ump->um_rootvp)
|
|
|
|
flags |= LK_CANRECURSE;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (lvp != NULLVP) {
|
2012-05-01 07:46:30 +00:00
|
|
|
if (uvp != NULLVP && flags & LK_UPGRADE) {
|
|
|
|
/* Share Lock is once released and a deadlock is avoided. */
|
|
|
|
VI_LOCK_FLAGS(uvp, MTX_DUPOK);
|
|
|
|
vholdl(uvp);
|
|
|
|
uhold = 1;
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
VOP_UNLOCK(uvp, LK_RELEASE | LK_INTERLOCK);
|
|
|
|
VI_LOCK(vp);
|
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
if (unp == NULL) {
|
|
|
|
/* vnode is released. */
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
VOP_UNLOCK(lvp, LK_RELEASE);
|
|
|
|
vdrop(uvp);
|
|
|
|
return (EBUSY);
|
|
|
|
}
|
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_LOCK_FLAGS(lvp, MTX_DUPOK);
|
|
|
|
flags |= LK_INTERLOCK;
|
|
|
|
vholdl(lvp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_UNLOCK(vp);
|
|
|
|
ap->a_flags &= ~LK_INTERLOCK;
|
|
|
|
|
2008-01-13 14:44:15 +00:00
|
|
|
error = VOP_LOCK(lvp, flags);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
VI_LOCK(vp);
|
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
if (unp == NULL) {
|
2012-05-01 07:46:30 +00:00
|
|
|
/* vnode is released. */
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_UNLOCK(vp);
|
2007-10-14 13:49:30 +00:00
|
|
|
if (error == 0)
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(lvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
vdrop(lvp);
|
2012-05-01 07:46:30 +00:00
|
|
|
if (uhold != 0)
|
|
|
|
vdrop(uvp);
|
2006-12-02 19:35:56 +00:00
|
|
|
return (vop_stdlock(ap));
|
|
|
|
}
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error == 0 && uvp != NULLVP) {
|
2012-05-01 07:46:30 +00:00
|
|
|
if (uhold && flags & LK_UPGRADE) {
|
|
|
|
flags &= ~LK_TYPE_MASK;
|
|
|
|
flags |= LK_EXCLUSIVE;
|
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_LOCK_FLAGS(uvp, MTX_DUPOK);
|
|
|
|
flags |= LK_INTERLOCK;
|
2012-05-01 07:46:30 +00:00
|
|
|
if (uhold == 0) {
|
|
|
|
vholdl(uvp);
|
|
|
|
uhold = 1;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
VI_UNLOCK(vp);
|
|
|
|
ap->a_flags &= ~LK_INTERLOCK;
|
|
|
|
|
2008-01-13 14:44:15 +00:00
|
|
|
error = VOP_LOCK(uvp, flags);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
VI_LOCK(vp);
|
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
if (unp == NULL) {
|
2012-05-01 07:46:30 +00:00
|
|
|
/* vnode is released. */
|
2007-10-14 13:49:30 +00:00
|
|
|
VI_UNLOCK(vp);
|
2012-05-01 07:46:30 +00:00
|
|
|
if (error == 0)
|
|
|
|
VOP_UNLOCK(uvp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
vdrop(uvp);
|
2012-05-01 07:46:30 +00:00
|
|
|
if (lvp != NULLVP) {
|
|
|
|
VOP_UNLOCK(lvp, LK_RELEASE);
|
|
|
|
vdrop(lvp);
|
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
return (vop_stdlock(ap));
|
|
|
|
}
|
2007-10-14 13:49:30 +00:00
|
|
|
if (error != 0 && lvp != NULLVP) {
|
2012-05-01 07:46:30 +00:00
|
|
|
/* rollback */
|
2007-10-14 13:49:30 +00:00
|
|
|
VI_UNLOCK(vp);
|
2012-05-01 07:46:30 +00:00
|
|
|
unionfs_revlock(lvp, revlock);
|
|
|
|
interlock = 0;
|
2007-10-14 13:49:30 +00:00
|
|
|
}
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
if (interlock)
|
|
|
|
VI_UNLOCK(vp);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (lvp != NULLVP)
|
|
|
|
vdrop(lvp);
|
|
|
|
if (uhold != 0)
|
|
|
|
vdrop(uvp);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
unionfs_lock_null_vnode:
|
|
|
|
ap->a_flags |= LK_INTERLOCK;
|
|
|
|
return (vop_stdlock(ap));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_unlock(struct vop_unlock_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
int flags;
|
|
|
|
int mtxlkflag;
|
|
|
|
int uhold;
|
|
|
|
struct vnode *vp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = 0;
|
|
|
|
mtxlkflag = 0;
|
|
|
|
uhold = 0;
|
|
|
|
flags = ap->a_flags | LK_RELEASE;
|
|
|
|
vp = ap->a_vp;
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
if ((flags & LK_INTERLOCK) != 0)
|
2006-12-02 19:35:56 +00:00
|
|
|
mtxlkflag = 1;
|
|
|
|
else if (mtx_owned(VI_MTX(vp)) == 0) {
|
|
|
|
VI_LOCK(vp);
|
|
|
|
mtxlkflag = 2;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
if (unp == NULL)
|
|
|
|
goto unionfs_unlock_null_vnode;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
|
|
|
|
if (lvp != NULLVP) {
|
|
|
|
VI_LOCK_FLAGS(lvp, MTX_DUPOK);
|
|
|
|
flags |= LK_INTERLOCK;
|
|
|
|
vholdl(lvp);
|
|
|
|
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
ap->a_flags &= ~LK_INTERLOCK;
|
|
|
|
|
2008-01-13 14:44:15 +00:00
|
|
|
error = VOP_UNLOCK(lvp, flags);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
VI_LOCK(vp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error == 0 && uvp != NULLVP) {
|
|
|
|
VI_LOCK_FLAGS(uvp, MTX_DUPOK);
|
|
|
|
flags |= LK_INTERLOCK;
|
|
|
|
vholdl(uvp);
|
|
|
|
uhold = 1;
|
|
|
|
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
ap->a_flags &= ~LK_INTERLOCK;
|
|
|
|
|
2008-01-13 14:44:15 +00:00
|
|
|
error = VOP_UNLOCK(uvp, flags);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
VI_LOCK(vp);
|
|
|
|
}
|
|
|
|
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
if (lvp != NULLVP)
|
|
|
|
vdrop(lvp);
|
|
|
|
if (uhold != 0)
|
|
|
|
vdrop(uvp);
|
|
|
|
if (mtxlkflag == 0)
|
|
|
|
VI_LOCK(vp);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
unionfs_unlock_null_vnode:
|
|
|
|
if (mtxlkflag == 2)
|
|
|
|
VI_UNLOCK(vp);
|
|
|
|
return (vop_stdunlock(ap));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_pathconf(struct vop_pathconf_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_advlock(struct vop_advlock_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
int error;
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct unionfs_node_status *unsp;
|
|
|
|
struct vnode *vp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct thread *td;
|
This is a major fixup of unionfs. At least 30 serious bugs have been
fixed (many due to changing semantics in other parts of the kernel and not
the original author's fault), including one critical one: unionfs could
cause UFS corruption in the fronting store due to calling VOP_OPEN for
writing without turning on vmio for the UFS vnode.
Most of the bugs were related to semantics changes in VOP calls, lock
ordering problems (causing deadlocks), improper handling of a read-only
backing store (such as an NFS mount), improper referencing and locking
of vnodes, not using real struct locks for vnode locking, not using
recursive locks when accessing the fronting store, and things like that.
New functionality has been added: unionfs now has mmap() support, but
only partially tested, and rename has been enhanced considerably.
There are still some things that unionfs cannot do. You cannot
rename a directory without confusing unionfs, and there are issues
with softlinks, hardlinks, and special files. unionfs mostly doesn't
understand them (and never did).
There are probably still panic situations, but hopefully no where near
as many as before this commit.
The unionfs in this commit has been tested overlayed on /usr/src
(backing /usr/src being a read-only NFS mount, fronting /usr/src being
a local filesystem). kernel builds have been tested, buildworld is
undergoing testing. More testing is necessary.
1999-09-26 20:52:41 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n");
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
vp = ap->a_vp;
|
|
|
|
td = curthread;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (uvp == NULLVP) {
|
|
|
|
error = unionfs_copyfile(unp, 1, td->td_ucred, td);
|
|
|
|
if (error != 0)
|
|
|
|
goto unionfs_advlock_abort;
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
|
|
|
|
unionfs_get_node_status(unp, td, &unsp);
|
|
|
|
if (unsp->uns_lower_opencnt > 0) {
|
|
|
|
/* try reopen the vnode */
|
2007-05-31 11:51:53 +00:00
|
|
|
error = VOP_OPEN(uvp, unsp->uns_lower_openmode,
|
|
|
|
td->td_ucred, td, NULL);
|
2006-12-02 19:35:56 +00:00
|
|
|
if (error)
|
|
|
|
goto unionfs_advlock_abort;
|
|
|
|
unsp->uns_upper_opencnt++;
|
|
|
|
VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, td->td_ucred, td);
|
|
|
|
unsp->uns_lower_opencnt--;
|
2007-10-14 13:42:05 +00:00
|
|
|
} else
|
2008-04-25 11:37:20 +00:00
|
|
|
unionfs_tryrem_node_status(unp, unsp);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
unionfs_advlock_abort:
|
2012-05-01 07:46:30 +00:00
|
|
|
VOP_UNLOCK(vp, LK_RELEASE);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-05-07 14:37:32 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_strategy(struct vop_strategy_args *ap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
#ifdef DIAGNOSTIC
|
2006-12-02 19:35:56 +00:00
|
|
|
if (vp == NULLVP)
|
|
|
|
panic("unionfs_strategy: nullvp");
|
|
|
|
|
|
|
|
if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp)
|
|
|
|
panic("unionfs_strategy: writing to lowervp");
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
return (VOP_STRATEGY(vp, ap->a_bp));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2004-01-03 00:36:46 +00:00
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_getacl(struct vop_getacl_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n");
|
|
|
|
|
|
|
|
error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_setacl(struct vop_setacl_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
td = ap->a_td;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (uvp == NULLVP && lvp->v_type == VREG) {
|
|
|
|
if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0)
|
|
|
|
return (error);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uvp != NULLVP)
|
|
|
|
error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_aclcheck(struct vop_aclcheck_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error);
|
|
|
|
|
|
|
|
return (error);
|
2004-01-03 00:36:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_openextattr(struct vop_openextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
2007-10-14 13:49:30 +00:00
|
|
|
struct vnode *tvp;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
vp = ap->a_vp;
|
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) ||
|
|
|
|
(tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL)))
|
2006-12-02 19:35:56 +00:00
|
|
|
return (EBUSY);
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
if (error == 0) {
|
2012-05-01 07:46:30 +00:00
|
|
|
if (vn_lock(vp, LK_UPGRADE) != 0)
|
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2007-10-14 13:49:30 +00:00
|
|
|
if (tvp == unp->un_uppervp)
|
2006-12-02 19:35:56 +00:00
|
|
|
unp->un_flag |= UNIONFS_OPENEXTU;
|
|
|
|
else
|
|
|
|
unp->un_flag |= UNIONFS_OPENEXTL;
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_closeextattr(struct vop_closeextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
2007-10-14 13:49:30 +00:00
|
|
|
struct vnode *tvp;
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
vp = ap->a_vp;
|
|
|
|
unp = VTOUNIONFS(vp);
|
|
|
|
tvp = NULLVP;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unp->un_flag & UNIONFS_OPENEXTU)
|
2007-10-14 13:49:30 +00:00
|
|
|
tvp = unp->un_uppervp;
|
2006-12-02 19:35:56 +00:00
|
|
|
else if (unp->un_flag & UNIONFS_OPENEXTL)
|
2007-10-14 13:49:30 +00:00
|
|
|
tvp = unp->un_lowervp;
|
2006-12-02 19:35:56 +00:00
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
if (tvp == NULLVP)
|
2006-12-02 19:35:56 +00:00
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
2007-10-14 13:49:30 +00:00
|
|
|
error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td);
|
2006-12-02 19:35:56 +00:00
|
|
|
|
|
|
|
if (error == 0) {
|
2012-05-01 07:46:30 +00:00
|
|
|
if (vn_lock(vp, LK_UPGRADE) != 0)
|
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2007-10-14 13:49:30 +00:00
|
|
|
if (tvp == unp->un_uppervp)
|
2006-12-02 19:35:56 +00:00
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTU;
|
|
|
|
else
|
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTL;
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
|
2006-12-02 19:35:56 +00:00
|
|
|
}
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_getextattr(struct vop_getextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = NULLVP;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unp->un_flag & UNIONFS_OPENEXTU)
|
|
|
|
vp = unp->un_uppervp;
|
|
|
|
else if (unp->un_flag & UNIONFS_OPENEXTL)
|
|
|
|
vp = unp->un_lowervp;
|
|
|
|
|
|
|
|
if (vp == NULLVP)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name,
|
|
|
|
ap->a_uio, ap->a_size, ap->a_cred, ap->a_td));
|
2004-01-03 00:36:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_setextattr(struct vop_setextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct vnode *ovp;
|
|
|
|
struct ucred *cred;
|
|
|
|
struct thread *td;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
ovp = NULLVP;
|
|
|
|
cred = ap->a_cred;
|
|
|
|
td = ap->a_td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n", unp->un_flag);
|
|
|
|
|
|
|
|
if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (unp->un_flag & UNIONFS_OPENEXTU)
|
|
|
|
ovp = unp->un_uppervp;
|
|
|
|
else if (unp->un_flag & UNIONFS_OPENEXTL)
|
|
|
|
ovp = unp->un_lowervp;
|
|
|
|
|
|
|
|
if (ovp == NULLVP)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
if (ovp == lvp && lvp->v_type == VREG) {
|
|
|
|
VOP_CLOSEEXTATTR(lvp, 0, cred, td);
|
|
|
|
if (uvp == NULLVP &&
|
|
|
|
(error = unionfs_copyfile(unp, 1, cred, td)) != 0) {
|
|
|
|
unionfs_setextattr_reopen:
|
|
|
|
if ((unp->un_flag & UNIONFS_OPENEXTL) &&
|
|
|
|
VOP_OPENEXTATTR(lvp, cred, td)) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
panic("unionfs: VOP_OPENEXTATTR failed");
|
|
|
|
#endif
|
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTL;
|
|
|
|
}
|
|
|
|
goto unionfs_setextattr_abort;
|
|
|
|
}
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
|
|
|
|
goto unionfs_setextattr_reopen;
|
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTL;
|
|
|
|
unp->un_flag |= UNIONFS_OPENEXTU;
|
|
|
|
ovp = uvp;
|
|
|
|
}
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ovp == uvp)
|
|
|
|
error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
|
|
|
|
ap->a_uio, cred, td);
|
|
|
|
|
|
|
|
unionfs_setextattr_abort:
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_listextattr(struct vop_listextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *vp;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
vp = NULLVP;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (unp->un_flag & UNIONFS_OPENEXTU)
|
|
|
|
vp = unp->un_uppervp;
|
|
|
|
else if (unp->un_flag & UNIONFS_OPENEXTL)
|
|
|
|
vp = unp->un_lowervp;
|
|
|
|
|
|
|
|
if (vp == NULLVP)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio,
|
|
|
|
ap->a_size, ap->a_cred, ap->a_td));
|
2004-01-03 00:36:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_deleteextattr(struct vop_deleteextattr_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct vnode *ovp;
|
|
|
|
struct ucred *cred;
|
|
|
|
struct thread *td;
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
ovp = NULLVP;
|
|
|
|
cred = ap->a_cred;
|
|
|
|
td = ap->a_td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n", unp->un_flag);
|
|
|
|
|
|
|
|
if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (unp->un_flag & UNIONFS_OPENEXTU)
|
|
|
|
ovp = unp->un_uppervp;
|
|
|
|
else if (unp->un_flag & UNIONFS_OPENEXTL)
|
|
|
|
ovp = unp->un_lowervp;
|
|
|
|
|
|
|
|
if (ovp == NULLVP)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
|
|
|
if (ovp == lvp && lvp->v_type == VREG) {
|
|
|
|
VOP_CLOSEEXTATTR(lvp, 0, cred, td);
|
|
|
|
if (uvp == NULLVP &&
|
|
|
|
(error = unionfs_copyfile(unp, 1, cred, td)) != 0) {
|
|
|
|
unionfs_deleteextattr_reopen:
|
|
|
|
if ((unp->un_flag & UNIONFS_OPENEXTL) &&
|
|
|
|
VOP_OPENEXTATTR(lvp, cred, td)) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
panic("unionfs: VOP_OPENEXTATTR failed");
|
|
|
|
#endif
|
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTL;
|
|
|
|
}
|
|
|
|
goto unionfs_deleteextattr_abort;
|
|
|
|
}
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
|
|
|
|
goto unionfs_deleteextattr_reopen;
|
|
|
|
unp->un_flag &= ~UNIONFS_OPENEXTL;
|
|
|
|
unp->un_flag |= UNIONFS_OPENEXTU;
|
|
|
|
ovp = uvp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ovp == uvp)
|
|
|
|
error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
|
|
|
|
ap->a_cred, ap->a_td);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_deleteextattr_abort:
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-12-02 19:35:56 +00:00
|
|
|
unionfs_setlabel(struct vop_setlabel_args *ap)
|
2004-01-03 00:36:46 +00:00
|
|
|
{
|
2006-12-02 19:35:56 +00:00
|
|
|
int error;
|
|
|
|
struct unionfs_node *unp;
|
|
|
|
struct vnode *uvp;
|
|
|
|
struct vnode *lvp;
|
|
|
|
struct thread *td;
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n");
|
|
|
|
|
2008-11-25 03:18:35 +00:00
|
|
|
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
error = EROFS;
|
|
|
|
unp = VTOUNIONFS(ap->a_vp);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
lvp = unp->un_lowervp;
|
|
|
|
td = ap->a_td;
|
2004-01-03 00:36:46 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
|
|
|
|
return (EROFS);
|
|
|
|
|
|
|
|
if (uvp == NULLVP && lvp->v_type == VREG) {
|
|
|
|
if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0)
|
|
|
|
return (error);
|
|
|
|
uvp = unp->un_uppervp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uvp != NULLVP)
|
|
|
|
error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td);
|
|
|
|
|
|
|
|
UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error);
|
2004-01-03 00:36:46 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2007-02-15 22:08:35 +00:00
|
|
|
static int
|
|
|
|
unionfs_vptofh(struct vop_vptofh_args *ap)
|
|
|
|
{
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
struct vop_vector unionfs_vnodeops = {
|
2004-12-01 23:16:38 +00:00
|
|
|
.vop_default = &default_vnodeops,
|
2005-01-13 18:59:48 +00:00
|
|
|
|
2006-12-02 19:35:56 +00:00
|
|
|
.vop_access = unionfs_access,
|
|
|
|
.vop_aclcheck = unionfs_aclcheck,
|
|
|
|
.vop_advlock = unionfs_advlock,
|
2004-12-01 23:16:38 +00:00
|
|
|
.vop_bmap = VOP_EOPNOTSUPP,
|
2007-10-14 13:46:11 +00:00
|
|
|
.vop_cachedlookup = unionfs_lookup,
|
2006-12-02 19:35:56 +00:00
|
|
|
.vop_close = unionfs_close,
|
|
|
|
.vop_closeextattr = unionfs_closeextattr,
|
|
|
|
.vop_create = unionfs_create,
|
|
|
|
.vop_deleteextattr = unionfs_deleteextattr,
|
|
|
|
.vop_fsync = unionfs_fsync,
|
|
|
|
.vop_getacl = unionfs_getacl,
|
|
|
|
.vop_getattr = unionfs_getattr,
|
|
|
|
.vop_getextattr = unionfs_getextattr,
|
|
|
|
.vop_getwritemount = unionfs_getwritemount,
|
|
|
|
.vop_inactive = unionfs_inactive,
|
2012-05-01 07:46:30 +00:00
|
|
|
.vop_islocked = unionfs_islocked,
|
2006-12-02 19:35:56 +00:00
|
|
|
.vop_ioctl = unionfs_ioctl,
|
|
|
|
.vop_link = unionfs_link,
|
|
|
|
.vop_listextattr = unionfs_listextattr,
|
2007-05-18 13:02:13 +00:00
|
|
|
.vop_lock1 = unionfs_lock,
|
2007-10-14 13:46:11 +00:00
|
|
|
.vop_lookup = vfs_cache_lookup,
|
2006-12-02 19:35:56 +00:00
|
|
|
.vop_mkdir = unionfs_mkdir,
|
|
|
|
.vop_mknod = unionfs_mknod,
|
|
|
|
.vop_open = unionfs_open,
|
|
|
|
.vop_openextattr = unionfs_openextattr,
|
|
|
|
.vop_pathconf = unionfs_pathconf,
|
|
|
|
.vop_poll = unionfs_poll,
|
|
|
|
.vop_print = unionfs_print,
|
|
|
|
.vop_read = unionfs_read,
|
|
|
|
.vop_readdir = unionfs_readdir,
|
|
|
|
.vop_readlink = unionfs_readlink,
|
|
|
|
.vop_reclaim = unionfs_reclaim,
|
|
|
|
.vop_remove = unionfs_remove,
|
|
|
|
.vop_rename = unionfs_rename,
|
|
|
|
.vop_rmdir = unionfs_rmdir,
|
|
|
|
.vop_setacl = unionfs_setacl,
|
|
|
|
.vop_setattr = unionfs_setattr,
|
|
|
|
.vop_setextattr = unionfs_setextattr,
|
|
|
|
.vop_setlabel = unionfs_setlabel,
|
|
|
|
.vop_strategy = unionfs_strategy,
|
|
|
|
.vop_symlink = unionfs_symlink,
|
|
|
|
.vop_unlock = unionfs_unlock,
|
|
|
|
.vop_whiteout = unionfs_whiteout,
|
|
|
|
.vop_write = unionfs_write,
|
2007-02-15 22:08:35 +00:00
|
|
|
.vop_vptofh = unionfs_vptofh,
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|