/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/t_lock.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/signal.h>
#include <sys/cred.h>
#include <sys/proc.h>
#include <sys/disp.h>
#include <sys/user.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <sys/mode.h>
#include <sys/buf.h>
#include <sys/uio.h>
#include <sys/dnlc.h>
#include <sys/pathname.h>
#include <sys/fs/ufs_inode.h>
#include <sys/fs/ufs_fs.h>
#include <sys/mount.h>
#include <sys/fs/ufs_fsdir.h>
#include <sys/fs/ufs_trans.h>
#include <sys/fs/ufs_panic.h>
#include <sys/fs/ufs_quota.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include <vm/seg.h>
#include <sys/sysmacros.h>
#include <sys/cmn_err.h>
#include <sys/cpuvar.h>
#include <sys/unistd.h>
int
ufs_xattr_getattrdir(
vnode_t *dvp,
struct inode **sip,
int flags,
struct cred *cr)
{
struct vfs *vfsp;
struct inode *ip, *sdp;
int error;
ip = VTOI(dvp);
if (flags & LOOKUP_XATTR) {
if (ip && ((ip->i_oeftflag) != 0)) {
vfsp = dvp->v_vfsp;
error = ufs_iget(vfsp, ip->i_oeftflag, sip, cr);
if (error)
return (error);
sdp = *sip;
/*
* Make sure it really is an ATTRDIR
*/
if ((sdp->i_mode & IFMT) != IFATTRDIR) {
cmn_err(CE_NOTE, "ufs_getattrdir: inode %d"
" points to attribute directory %d "
"which is not an attribute directory;"
"run fsck on file system",
(int)ip->i_number, (int)sdp->i_number);
VN_RELE(ITOV(sdp));
return (ENOENT);
}
ITOV(sdp)->v_type = VDIR;
ITOV(sdp)->v_flag |= V_XATTRDIR;
error = 0;
goto out;
} else if (flags & CREATE_XATTR_DIR) {
error = ufs_xattrmkdir(ip, sip, 1, cr);
} else {
error = ENOENT;
goto out;
}
} else if (flags & CREATE_XATTR_DIR) {
error = ufs_xattrmkdir(ip, sip, 1, cr);
} else {
error = ENOENT;
}
out:
return (error);
}
/*
* Unhook an attribute directory from a parent file/dir
* Only do so, if we are the only user of the vnode.
*/
void
ufs_unhook_shadow(struct inode *ip, struct inode *sip)
{
struct vnode *datavp = ITOV(ip);
struct vnode *dirvp = ITOV(sip);
int hno;
kmutex_t *ihm;
ASSERT(RW_WRITE_HELD(&sip->i_contents));
ASSERT(RW_WRITE_HELD(&ip->i_contents));
if (vn_is_readonly(ITOV(ip)))
return;
if (ip->i_ufsvfs == NULL || sip->i_ufsvfs == NULL)
return;
hno = INOHASH(ip->i_number);
ihm = &ih_lock[hno];
mutex_enter(ihm);
mutex_enter(&datavp->v_lock);
mutex_enter(&dirvp->v_lock);
if (dirvp->v_count != 1 && datavp->v_count != 1) {
mutex_exit(&dirvp->v_lock);
mutex_exit(&datavp->v_lock);
mutex_exit(ihm);
return;
}
/*
* Delete shadow from ip
*/
sip->i_nlink -= 2;
ufs_setreclaim(sip);
TRANS_INODE(sip->i_ufsvfs, sip);
sip->i_flag |= ICHG;
sip->i_seq++;
ITIMES_NOLOCK(sip);
/*
* Update src file
*/
ip->i_oeftflag = 0;
TRANS_INODE(ip->i_ufsvfs, ip);
ip->i_flag |= ICHG;
ip->i_seq++;
ufs_iupdat(ip, 1);
mutex_exit(&dirvp->v_lock);
mutex_exit(&datavp->v_lock);
mutex_exit(ihm);
}