/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); }